1251877Speter/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
2251877Speter *
3251877Speter * Licensed under the Apache License, Version 2.0 (the "License");
4251877Speter * you may not use this file except in compliance with the License.
5251877Speter * You may obtain a copy of the License at
6251877Speter *
7251877Speter *     http://www.apache.org/licenses/LICENSE-2.0
8251877Speter *
9251877Speter * Unless required by applicable law or agreed to in writing, software
10251877Speter * distributed under the License is distributed on an "AS IS" BASIS,
11251877Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12251877Speter * See the License for the specific language governing permissions and
13251877Speter * limitations under the License.
14251877Speter */
15251877Speter
16251877Speter#ifndef SERF_H
17251877Speter#define SERF_H
18251877Speter
19251877Speter/**
20251877Speter * @file serf.h
21251877Speter * @brief Main serf header file
22251877Speter */
23251877Speter
24251877Speter#include <apr.h>
25251877Speter#include <apr_errno.h>
26251877Speter#include <apr_allocator.h>
27251877Speter#include <apr_pools.h>
28251877Speter#include <apr_network_io.h>
29251877Speter#include <apr_time.h>
30251877Speter#include <apr_poll.h>
31251877Speter#include <apr_uri.h>
32251877Speter
33251877Speter#ifdef __cplusplus
34251877Speterextern "C" {
35251877Speter#endif
36251877Speter
37251877Speter/* Forward declare some structures */
38251877Spetertypedef struct serf_context_t serf_context_t;
39251877Speter
40251877Spetertypedef struct serf_bucket_t serf_bucket_t;
41251877Spetertypedef struct serf_bucket_type_t serf_bucket_type_t;
42251877Spetertypedef struct serf_bucket_alloc_t serf_bucket_alloc_t;
43251877Speter
44251877Spetertypedef struct serf_connection_t serf_connection_t;
45251877Spetertypedef struct serf_listener_t serf_listener_t;
46251877Spetertypedef struct serf_incoming_t serf_incoming_t;
47251877Spetertypedef struct serf_incoming_request_t serf_incoming_request_t;
48251877Speter
49251877Spetertypedef struct serf_request_t serf_request_t;
50251877Speter
51251877Speter
52251877Speter/**
53251877Speter * @defgroup serf high-level constructs
54251877Speter * @ingroup serf
55251877Speter * @{
56251877Speter */
57251877Speter
58251877Speter/**
59251877Speter * Serf-specific error codes
60251877Speter */
61251877Speter#define SERF_ERROR_RANGE 100
62253895Speter#define SERF_ERROR_START (APR_OS_START_USERERR + SERF_ERROR_RANGE)
63251877Speter
64251877Speter/* This code is for when this is the last response on this connection:
65251877Speter * i.e. do not send any more requests on this connection or expect
66251877Speter * any more responses.
67251877Speter */
68253895Speter#define SERF_ERROR_CLOSING (SERF_ERROR_START + 1)
69251877Speter/* This code is for when the connection terminated before the request
70251877Speter * could be processed on the other side.
71251877Speter */
72253895Speter#define SERF_ERROR_REQUEST_LOST (SERF_ERROR_START + 2)
73251877Speter/* This code is for when the connection is blocked - we can not proceed
74251877Speter * until something happens - generally due to SSL negotiation-like behavior
75251877Speter * where a write() is blocked until a read() is processed.
76251877Speter */
77253895Speter#define SERF_ERROR_WAIT_CONN (SERF_ERROR_START + 3)
78251877Speter/* This code is for when something went wrong during deflating compressed
79251877Speter * data e.g. a CRC error. */
80253895Speter#define SERF_ERROR_DECOMPRESSION_FAILED (SERF_ERROR_START + 4)
81251877Speter/* This code is for when a response received from a http server is not in
82251877Speter * http-compliant syntax. */
83253895Speter#define SERF_ERROR_BAD_HTTP_RESPONSE (SERF_ERROR_START + 5)
84251877Speter/* The server sent less data than what was announced. */
85253895Speter#define SERF_ERROR_TRUNCATED_HTTP_RESPONSE (SERF_ERROR_START + 6)
86251877Speter/* The proxy server returned an error while setting up the SSL tunnel. */
87253895Speter#define SERF_ERROR_SSLTUNNEL_SETUP_FAILED (SERF_ERROR_START + 7)
88251877Speter/* The server unexpectedly closed the connection prematurely. */
89253895Speter#define SERF_ERROR_ABORTED_CONNECTION (SERF_ERROR_START + 8)
90251877Speter
91251877Speter/* SSL certificates related errors */
92253895Speter#define SERF_ERROR_SSL_CERT_FAILED (SERF_ERROR_START + 70)
93251877Speter
94251877Speter/* SSL communications related errors */
95253895Speter#define SERF_ERROR_SSL_COMM_FAILED (SERF_ERROR_START + 71)
96251877Speter
97251877Speter/* General authentication related errors */
98253895Speter#define SERF_ERROR_AUTHN_FAILED (SERF_ERROR_START + 90)
99251877Speter
100251877Speter/* None of the available authn mechanisms for the request are supported */
101253895Speter#define SERF_ERROR_AUTHN_NOT_SUPPORTED (SERF_ERROR_START + 91)
102251877Speter
103251877Speter/* Authn was requested by the server but the header lacked some attribute  */
104253895Speter#define SERF_ERROR_AUTHN_MISSING_ATTRIBUTE (SERF_ERROR_START + 92)
105251877Speter
106251877Speter/* Authentication handler initialization related errors */
107253895Speter#define SERF_ERROR_AUTHN_INITALIZATION_FAILED (SERF_ERROR_START + 93)
108251877Speter
109253895Speter/* Error code reserved for use in the test suite. */
110253895Speter#define SERF_ERROR_ISSUE_IN_TESTSUITE (SERF_ERROR_START + 99)
111253895Speter
112251877Speter/* This macro groups errors potentially raised when reading a http response.  */
113251877Speter#define SERF_BAD_RESPONSE_ERROR(status) ((status) \
114251877Speter    && ((SERF_ERROR_DECOMPRESSION_FAILED == (status)) \
115251877Speter        ||(SERF_ERROR_BAD_HTTP_RESPONSE == (status)) \
116251877Speter        ||(SERF_ERROR_TRUNCATED_HTTP_RESPONSE == (status))))
117251877Speter
118251877Speter/**
119251877Speter * Return a string that describes the specified error code.
120251877Speter *
121251877Speter * If the error code is not one of the above Serf error codes, then
122251877Speter * NULL will be returned.
123251877Speter *
124251877Speter * Note regarding lifetime: the string is a statically-allocated constant
125251877Speter */
126251877Speterconst char *serf_error_string(apr_status_t errcode);
127251877Speter
128251877Speter
129251877Speter/**
130251877Speter * Create a new context for serf operations.
131251877Speter *
132251877Speter * A serf context defines a control loop which processes multiple
133251877Speter * connections simultaneously.
134251877Speter *
135251877Speter * The context will be allocated within @a pool.
136251877Speter */
137251877Speterserf_context_t *serf_context_create(
138251877Speter    apr_pool_t *pool);
139251877Speter
140251877Speter/**
141251877Speter * Callback function. Add a socket to the externally managed poll set.
142251877Speter *
143251877Speter * Both @a pfd and @a serf_baton should be used when calling serf_event_trigger
144251877Speter * later.
145251877Speter */
146251877Spetertypedef apr_status_t (*serf_socket_add_t)(
147251877Speter    void *user_baton,
148251877Speter    apr_pollfd_t *pfd,
149251877Speter    void *serf_baton);
150251877Speter
151251877Speter/**
152251877Speter * Callback function. Remove the socket, identified by both @a pfd and
153251877Speter * @a serf_baton from the externally managed poll set.
154251877Speter */
155251877Spetertypedef apr_status_t (*serf_socket_remove_t)(
156251877Speter    void *user_baton,
157251877Speter    apr_pollfd_t *pfd,
158251877Speter    void *serf_baton);
159251877Speter
160251877Speter/* Create a new context for serf operations.
161251877Speter *
162251877Speter * Use this function to make serf not use its internal control loop, but
163251877Speter * instead rely on an external event loop. Serf will use the @a addf and @a rmf
164251877Speter * callbacks to notify of any event on a connection. The @a user_baton will be
165251877Speter * passed through the addf and rmf callbacks.
166251877Speter *
167251877Speter * The context will be allocated within @a pool.
168251877Speter */
169251877Speterserf_context_t *serf_context_create_ex(
170251877Speter    void *user_baton,
171251877Speter    serf_socket_add_t addf,
172251877Speter    serf_socket_remove_t rmf,
173251877Speter    apr_pool_t *pool);
174251877Speter
175251877Speter/**
176251877Speter * Make serf process events on a connection, identified by both @a pfd and
177251877Speter * @a serf_baton.
178251877Speter *
179251877Speter * Any outbound data is delivered, and incoming data is made available to
180251877Speter * the associated response handlers and their buckets.
181251877Speter *
182251877Speter * If any data is processed (incoming or outgoing), then this function will
183251877Speter * return with APR_SUCCESS.
184251877Speter */
185251877Speterapr_status_t serf_event_trigger(
186251877Speter    serf_context_t *s,
187251877Speter    void *serf_baton,
188251877Speter    const apr_pollfd_t *pfd);
189251877Speter
190251877Speter/** @see serf_context_run should not block at all. */
191251877Speter#define SERF_DURATION_NOBLOCK 0
192251877Speter/** @see serf_context_run should run for (nearly) "forever". */
193251877Speter#define SERF_DURATION_FOREVER 2000000000        /* approx 1^31 */
194251877Speter
195251877Speter/**
196251877Speter * Run the main networking control loop.
197251877Speter *
198251877Speter * The set of connections defined by the serf context @a ctx are processed.
199251877Speter * Any outbound data is delivered, and incoming data is made available to
200251877Speter * the associated response handlers and their buckets. This function will
201251877Speter * block on the network for no longer than @a duration microseconds.
202251877Speter *
203251877Speter * If any data is processed (incoming or outgoing), then this function will
204251877Speter * return with APR_SUCCESS. Typically, the caller will just want to call it
205251877Speter * again to continue processing data.
206251877Speter *
207251877Speter * If no activity occurs within the specified timeout duration, then
208251877Speter * APR_TIMEUP is returned.
209251877Speter *
210251877Speter * All temporary allocations will be made in @a pool.
211251877Speter */
212251877Speterapr_status_t serf_context_run(
213251877Speter    serf_context_t *ctx,
214251877Speter    apr_short_interval_time_t duration,
215251877Speter    apr_pool_t *pool);
216251877Speter
217251877Speter
218251877Speterapr_status_t serf_context_prerun(
219251877Speter    serf_context_t *ctx);
220251877Speter
221251877Speter/**
222251877Speter * Callback function for progress information. @a progress indicates cumulative
223251877Speter * number of bytes read or written, for the whole context.
224251877Speter */
225251877Spetertypedef void (*serf_progress_t)(
226251877Speter    void *progress_baton,
227251877Speter    apr_off_t read,
228251877Speter    apr_off_t write);
229251877Speter
230251877Speter/**
231251877Speter * Sets the progress callback function. @a progress_func will be called every
232251877Speter * time bytes are read of or written on a socket.
233251877Speter */
234251877Spetervoid serf_context_set_progress_cb(
235251877Speter    serf_context_t *ctx,
236251877Speter    const serf_progress_t progress_func,
237251877Speter    void *progress_baton);
238251877Speter
239251877Speter/** @} */
240251877Speter
241251877Speter/**
242251877Speter * @defgroup serf connections and requests
243251877Speter * @ingroup serf
244251877Speter * @{
245251877Speter */
246251877Speter
247251877Speter/**
248251877Speter * When a connection is established, the application needs to wrap some
249251877Speter * buckets around @a skt to enable serf to process incoming responses. This
250251877Speter * is the control point for assembling connection-level processing logic
251251877Speter * around the given socket.
252251877Speter *
253251877Speter * The @a setup_baton is the baton established at connection creation time.
254251877Speter *
255251877Speter * This callback corresponds to reading from the server. Since this is an
256251877Speter * on-demand activity, we use a callback. The corresponding write operation
257251877Speter * is based on the @see serf_request_deliver function, where the application
258251877Speter * can assemble the appropriate bucket(s) before delivery.
259251877Speter *
260251877Speter * The returned bucket should live at least as long as the connection itself.
261251877Speter * It is assumed that an appropriate allocator is passed in @a setup_baton.
262251877Speter * ### we may want to create a connection-level allocator and pass that
263251877Speter * ### along. however, that allocator would *only* be used for this
264251877Speter * ### callback. it may be wasteful to create a per-conn allocator, so this
265251877Speter * ### baton-based, app-responsible form might be best.
266251877Speter *
267251877Speter * Responsibility for the buckets is passed to the serf library. They will be
268251877Speter * destroyed when the connection is closed.
269251877Speter *
270251877Speter * All temporary allocations should be made in @a pool.
271251877Speter */
272251877Spetertypedef apr_status_t (*serf_connection_setup_t)(
273251877Speter    apr_socket_t *skt,
274251877Speter    serf_bucket_t **read_bkt,
275251877Speter    serf_bucket_t **write_bkt,
276251877Speter    void *setup_baton,
277251877Speter    apr_pool_t *pool);
278251877Speter
279251877Speter/**
280251877Speter * ### need to update docco w.r.t socket. became "stream" recently.
281251877Speter * ### the stream does not have a barrier, this callback should generally
282251877Speter * ### add a barrier around the stream before incorporating it into a
283251877Speter * ### response bucket stack.
284251877Speter * ### should serf add the barrier automatically to protect its data
285251877Speter * ### structure? i.e. the passed bucket becomes owned rather than
286251877Speter * ### borrowed. that might suit overall semantics better.
287251877Speter * Accept an incoming response for @a request, and its @a socket. A bucket
288251877Speter * for the response should be constructed and returned. This is the control
289251877Speter * point for assembling the appropriate wrapper buckets around the socket to
290251877Speter * enable processing of the incoming response.
291251877Speter *
292251877Speter * The @a acceptor_baton is the baton provided when the specified request
293251877Speter * was created.
294251877Speter *
295251877Speter * The request's pool and bucket allocator should be used for any allocations
296251877Speter * that need to live for the duration of the response. Care should be taken
297251877Speter * to bound the amount of memory stored in this pool -- to ensure that
298251877Speter * allocations are not proportional to the amount of data in the response.
299251877Speter *
300251877Speter * Responsibility for the bucket is passed to the serf library. It will be
301251877Speter * destroyed when the response has been fully read (the bucket returns an
302251877Speter * APR_EOF status from its read functions).
303251877Speter *
304251877Speter * All temporary allocations should be made in @a pool.
305251877Speter */
306251877Speter/* ### do we need to return an error? */
307251877Spetertypedef serf_bucket_t * (*serf_response_acceptor_t)(
308251877Speter    serf_request_t *request,
309251877Speter    serf_bucket_t *stream,
310251877Speter    void *acceptor_baton,
311251877Speter    apr_pool_t *pool);
312251877Speter
313251877Speter/**
314251877Speter * Notification callback for when a connection closes.
315251877Speter *
316251877Speter * This callback is used to inform an application that the @a conn
317251877Speter * connection has been (abnormally) closed. The @a closed_baton is the
318251877Speter * baton provided when the connection was first opened. The reason for
319251877Speter * closure is given in @a why, and will be APR_SUCCESS if the application
320251877Speter * requested closure (by clearing the pool used to allocate this
321251877Speter * connection or calling serf_connection_close).
322251877Speter *
323251877Speter * All temporary allocations should be made in @a pool.
324251877Speter */
325251877Spetertypedef void (*serf_connection_closed_t)(
326251877Speter    serf_connection_t *conn,
327251877Speter    void *closed_baton,
328251877Speter    apr_status_t why,
329251877Speter    apr_pool_t *pool);
330251877Speter
331251877Speter/**
332251877Speter * Response data has arrived and should be processed.
333251877Speter *
334251877Speter * Whenever response data for @a request arrives (initially, or continued data
335251877Speter * arrival), this handler is invoked. The response data is available in the
336251877Speter * @a response bucket. The @a handler_baton is passed along from the baton
337251877Speter * provided by the request setup callback (@see serf_request_setup_t).
338251877Speter *
339251877Speter * The handler MUST process data from the @a response bucket until the
340251877Speter * bucket's read function states it would block (see APR_STATUS_IS_EAGAIN).
341251877Speter * The handler is invoked only when new data arrives. If no further data
342251877Speter * arrives, and the handler does not process all available data, then the
343251877Speter * system can result in a deadlock around the unprocessed, but read, data.
344251877Speter *
345251877Speter * The handler should return APR_EOF when the response has been fully read.
346251877Speter * If calling the handler again would block, APR_EAGAIN should be returned.
347251877Speter * If the handler should be invoked again, simply return APR_SUCCESS.
348251877Speter *
349251877Speter * Note: if the connection closed (at the request of the application, or
350251877Speter * because of an (abnormal) termination) while a request is being delivered,
351251877Speter * or before a response arrives, then @a response will be NULL. This is the
352251877Speter * signal that the request was not delivered properly, and no further
353251877Speter * response should be expected (this callback will not be invoked again).
354251877Speter * If a request is injected into the connection (during this callback's
355251877Speter * execution, or otherwise), then the connection will be reopened.
356251877Speter *
357251877Speter * All temporary allocations should be made in @a pool.
358251877Speter */
359251877Spetertypedef apr_status_t (*serf_response_handler_t)(
360251877Speter    serf_request_t *request,
361251877Speter    serf_bucket_t *response,
362251877Speter    void *handler_baton,
363251877Speter    apr_pool_t *pool);
364251877Speter
365251877Speter/**
366251877Speter * Callback function to be implemented by the application, so that serf
367251877Speter * can handle server and proxy authentication.
368251877Speter * code = 401 (server) or 407 (proxy).
369251877Speter * baton = the baton passed to serf_context_run.
370251877Speter * authn_type = one of "Basic", "Digest".
371251877Speter */
372251877Spetertypedef apr_status_t (*serf_credentials_callback_t)(
373251877Speter    char **username,
374251877Speter    char **password,
375251877Speter    serf_request_t *request, void *baton,
376251877Speter    int code, const char *authn_type,
377251877Speter    const char *realm,
378251877Speter    apr_pool_t *pool);
379251877Speter
380251877Speter/**
381251877Speter * Create a new connection associated with the @a ctx serf context.
382251877Speter *
383251877Speter * If no proxy server is configured, a connection will be created to
384251877Speter * (eventually) connect to the address specified by @a address. The address must
385251877Speter * live at least as long as @a pool (thus, as long as the connection object).
386251877Speter * If a proxy server is configured, @address will be ignored.
387251877Speter *
388251877Speter * The connection object will be allocated within @a pool. Clearing or
389251877Speter * destroying this pool will close the connection, and terminate any
390251877Speter * outstanding requests or responses.
391251877Speter *
392251877Speter * When the connection is closed (upon request or because of an error),
393251877Speter * then the @a closed callback is invoked, and @a closed_baton is passed.
394251877Speter *
395251877Speter * ### doc on setup(_baton). tweak below comment re: acceptor.
396251877Speter * NULL may be passed for @a acceptor and @a closed; default implementations
397251877Speter * will be used.
398251877Speter *
399251877Speter * Note: the connection is not made immediately. It will be opened on
400251877Speter * the next call to @see serf_context_run.
401251877Speter */
402251877Speterserf_connection_t *serf_connection_create(
403251877Speter    serf_context_t *ctx,
404251877Speter    apr_sockaddr_t *address,
405251877Speter    serf_connection_setup_t setup,
406251877Speter    void *setup_baton,
407251877Speter    serf_connection_closed_t closed,
408251877Speter    void *closed_baton,
409251877Speter    apr_pool_t *pool);
410251877Speter
411251877Speter/**
412251877Speter * Create a new connection associated with the @a ctx serf context.
413251877Speter *
414251877Speter * A connection will be created to (eventually) connect to the address
415251877Speter * specified by @a address. The address must live at least as long as
416251877Speter * @a pool (thus, as long as the connection object).
417251877Speter *
418251877Speter * The host address will be looked up based on the hostname in @a host_info.
419251877Speter *
420251877Speter * The connection object will be allocated within @a pool. Clearing or
421251877Speter * destroying this pool will close the connection, and terminate any
422251877Speter * outstanding requests or responses.
423251877Speter *
424251877Speter * When the connection is closed (upon request or because of an error),
425251877Speter * then the @a closed callback is invoked, and @a closed_baton is passed.
426251877Speter *
427251877Speter * ### doc on setup(_baton). tweak below comment re: acceptor.
428251877Speter * NULL may be passed for @a acceptor and @a closed; default implementations
429251877Speter * will be used.
430251877Speter *
431251877Speter * Note: the connection is not made immediately. It will be opened on
432251877Speter * the next call to @see serf_context_run.
433251877Speter */
434251877Speterapr_status_t serf_connection_create2(
435251877Speter    serf_connection_t **conn,
436251877Speter    serf_context_t *ctx,
437251877Speter    apr_uri_t host_info,
438251877Speter    serf_connection_setup_t setup,
439251877Speter    void *setup_baton,
440251877Speter    serf_connection_closed_t closed,
441251877Speter    void *closed_baton,
442251877Speter    apr_pool_t *pool);
443251877Speter
444251877Speter
445251877Spetertypedef apr_status_t (*serf_accept_client_t)(
446251877Speter    serf_context_t *ctx,
447251877Speter    serf_listener_t *l,
448251877Speter    void *accept_baton,
449251877Speter    apr_socket_t *insock,
450251877Speter    apr_pool_t *pool);
451251877Speter
452251877Speterapr_status_t serf_listener_create(
453251877Speter    serf_listener_t **listener,
454251877Speter    serf_context_t *ctx,
455251877Speter    const char *host,
456251877Speter    apr_uint16_t port,
457251877Speter    void *accept_baton,
458251877Speter    serf_accept_client_t accept_func,
459251877Speter    apr_pool_t *pool);
460251877Speter
461251877Spetertypedef apr_status_t (*serf_incoming_request_cb_t)(
462251877Speter    serf_context_t *ctx,
463251877Speter    serf_incoming_request_t *req,
464251877Speter    void *request_baton,
465251877Speter    apr_pool_t *pool);
466251877Speter
467251877Speterapr_status_t serf_incoming_create(
468251877Speter    serf_incoming_t **client,
469251877Speter    serf_context_t *ctx,
470251877Speter    apr_socket_t *insock,
471251877Speter    void *request_baton,
472251877Speter    serf_incoming_request_cb_t request,
473251877Speter    apr_pool_t *pool);
474251877Speter
475251877Speter
476251877Speter
477251877Speter
478251877Speter/**
479251877Speter * Reset the connection, but re-open the socket again.
480251877Speter */
481251877Speterapr_status_t serf_connection_reset(
482251877Speter    serf_connection_t *conn);
483251877Speter
484251877Speter/**
485251877Speter * Close the connection associated with @a conn and cancel all pending requests.
486251877Speter *
487251877Speter * The closed callback passed to serf_connection_create() will be invoked
488251877Speter * with APR_SUCCESS.
489251877Speter */
490251877Speterapr_status_t serf_connection_close(
491251877Speter    serf_connection_t *conn);
492251877Speter
493251877Speter/**
494251877Speter * Sets the maximum number of outstanding requests @a max_requests on the
495251877Speter * connection @a conn. Setting max_requests to 0 means unlimited (the default).
496251877Speter * Ex.: setting max_requests to 1 means a request is sent when a response on the
497251877Speter * previous request was received and handled.
498253895Speter *
499253895Speter * In general, serf tends to take around 16KB per outstanding request.
500251877Speter */
501251877Spetervoid serf_connection_set_max_outstanding_requests(
502251877Speter    serf_connection_t *conn,
503251877Speter    unsigned int max_requests);
504251877Speter
505251877Spetervoid serf_connection_set_async_responses(
506251877Speter    serf_connection_t *conn,
507251877Speter    serf_response_acceptor_t acceptor,
508251877Speter    void *acceptor_baton,
509251877Speter    serf_response_handler_t handler,
510251877Speter    void *handler_baton);
511251877Speter
512251877Speter/**
513251877Speter * Setup the @a request for delivery on its connection.
514251877Speter *
515251877Speter * Right before this is invoked, @a pool will be built within the
516251877Speter * connection's pool for the request to use.  The associated response will
517251877Speter * be allocated within that subpool. An associated bucket allocator will
518251877Speter * be built. These items may be fetched from the request object through
519251877Speter * @see serf_request_get_pool or @see serf_request_get_alloc.
520251877Speter *
521251877Speter * The content of the request is specified by the @a req_bkt bucket. When
522251877Speter * a response arrives, the @a acceptor callback will be invoked (along with
523251877Speter * the @a acceptor_baton) to produce a response bucket. That bucket will then
524251877Speter * be passed to @a handler, along with the @a handler_baton.
525251877Speter *
526251877Speter * The responsibility for the request bucket is passed to the request
527251877Speter * object. When the request is done with the bucket, it will be destroyed.
528251877Speter */
529251877Spetertypedef apr_status_t (*serf_request_setup_t)(
530251877Speter    serf_request_t *request,
531251877Speter    void *setup_baton,
532251877Speter    serf_bucket_t **req_bkt,
533251877Speter    serf_response_acceptor_t *acceptor,
534251877Speter    void **acceptor_baton,
535251877Speter    serf_response_handler_t *handler,
536251877Speter    void **handler_baton,
537251877Speter    apr_pool_t *pool);
538251877Speter
539251877Speter/**
540251877Speter * Construct a request object for the @a conn connection.
541251877Speter *
542251877Speter * When it is time to deliver the request, the @a setup callback will
543251877Speter * be invoked with the @a setup_baton passed into it to complete the
544251877Speter * construction of the request object.
545251877Speter *
546251877Speter * If the request has not (yet) been delivered, then it may be canceled
547251877Speter * with @see serf_request_cancel.
548251877Speter *
549251877Speter * Invoking any calls other than @see serf_request_cancel before the setup
550251877Speter * callback executes is not supported.
551251877Speter */
552251877Speterserf_request_t *serf_connection_request_create(
553251877Speter    serf_connection_t *conn,
554251877Speter    serf_request_setup_t setup,
555251877Speter    void *setup_baton);
556251877Speter
557251877Speter/**
558251877Speter * Construct a request object for the @a conn connection, add it in the
559251877Speter * list as the next to-be-written request before all unwritten requests.
560251877Speter *
561251877Speter * When it is time to deliver the request, the @a setup callback will
562251877Speter * be invoked with the @a setup_baton passed into it to complete the
563251877Speter * construction of the request object.
564251877Speter *
565251877Speter * If the request has not (yet) been delivered, then it may be canceled
566251877Speter * with @see serf_request_cancel.
567251877Speter *
568251877Speter * Invoking any calls other than @see serf_request_cancel before the setup
569251877Speter * callback executes is not supported.
570251877Speter */
571251877Speterserf_request_t *serf_connection_priority_request_create(
572251877Speter    serf_connection_t *conn,
573251877Speter    serf_request_setup_t setup,
574251877Speter    void *setup_baton);
575251877Speter
576251877Speter
577251877Speter/** Returns detected network latency for the @a conn connection. Negative
578251877Speter *  value means that latency is unknwon.
579251877Speter */
580251877Speterapr_interval_time_t serf_connection_get_latency(serf_connection_t *conn);
581251877Speter
582251877Speter/** Check if a @a request has been completely written.
583251877Speter *
584251877Speter * Returns APR_SUCCESS if the request was written completely on the connection.
585251877Speter * Returns APR_EBUSY if the request is not yet or partially written.
586251877Speter */
587251877Speterapr_status_t serf_request_is_written(
588251877Speter    serf_request_t *request);
589251877Speter
590251877Speter/**
591251877Speter * Cancel the request specified by the @a request object.
592251877Speter *
593251877Speter * If the request has been scheduled for delivery, then its response
594251877Speter * handler will be run, passing NULL for the response bucket.
595251877Speter *
596251877Speter * If the request has already been (partially or fully) delivered, then
597251877Speter * APR_EBUSY is returned and the request is *NOT* canceled. To properly
598251877Speter * cancel the request, the connection must be closed (by clearing or
599251877Speter * destroying its associated pool).
600251877Speter */
601251877Speterapr_status_t serf_request_cancel(
602251877Speter    serf_request_t *request);
603251877Speter
604251877Speter/**
605251877Speter * Return the pool associated with @a request.
606251877Speter *
607251877Speter * WARNING: be very careful about the kinds of things placed into this
608251877Speter * pool. In particular, all allocation should be bounded in size, rather
609251877Speter * than proportional to any data stream.
610251877Speter */
611251877Speterapr_pool_t *serf_request_get_pool(
612251877Speter    const serf_request_t *request);
613251877Speter
614251877Speter/**
615251877Speter * Return the bucket allocator associated with @a request.
616251877Speter */
617251877Speterserf_bucket_alloc_t *serf_request_get_alloc(
618251877Speter    const serf_request_t *request);
619251877Speter
620251877Speter/**
621251877Speter * Return the connection associated with @a request.
622251877Speter */
623251877Speterserf_connection_t *serf_request_get_conn(
624251877Speter    const serf_request_t *request);
625251877Speter
626251877Speter/**
627251877Speter * Update the @a handler and @a handler_baton for this @a request.
628251877Speter *
629251877Speter * This can be called after the request has started processing -
630251877Speter * subsequent data will be delivered to this new handler.
631251877Speter */
632251877Spetervoid serf_request_set_handler(
633251877Speter    serf_request_t *request,
634251877Speter    const serf_response_handler_t handler,
635251877Speter    const void **handler_baton);
636251877Speter
637251877Speter/**
638251877Speter * Configure proxy server settings, to be used by all connections associated
639251877Speter * with the @a ctx serf context.
640251877Speter *
641251877Speter * The next connection will be created to connect to the proxy server
642251877Speter * specified by @a address. The address must live at least as long as the
643251877Speter * serf context.
644251877Speter */
645251877Spetervoid serf_config_proxy(
646251877Speter    serf_context_t *ctx,
647251877Speter    apr_sockaddr_t *address);
648251877Speter
649251877Speter/* Supported authentication types. */
650251877Speter#define SERF_AUTHN_NONE      0x00
651251877Speter#define SERF_AUTHN_BASIC     0x01
652251877Speter#define SERF_AUTHN_DIGEST    0x02
653251877Speter#define SERF_AUTHN_NTLM      0x04
654251877Speter#define SERF_AUTHN_NEGOTIATE 0x08
655251877Speter#define SERF_AUTHN_ALL       0xFF
656251877Speter
657251877Speter/**
658251877Speter * Define the authentication handlers that serf will try on incoming requests.
659251877Speter */
660251877Spetervoid serf_config_authn_types(
661251877Speter    serf_context_t *ctx,
662251877Speter    int authn_types);
663251877Speter
664251877Speter/**
665251877Speter * Set the credentials callback handler.
666251877Speter */
667251877Spetervoid serf_config_credentials_callback(
668251877Speter    serf_context_t *ctx,
669251877Speter    serf_credentials_callback_t cred_cb);
670251877Speter
671251877Speter/* ### maybe some connection control functions for flood? */
672251877Speter
673251877Speter/*** Special bucket creation functions ***/
674251877Speter
675251877Speter/**
676251877Speter * Create a bucket of type 'socket bucket'.
677251877Speter * This is basically a wrapper around @a serf_bucket_socket_create, which
678251877Speter * initializes the bucket using connection and/or context specific settings.
679251877Speter */
680251877Speterserf_bucket_t *serf_context_bucket_socket_create(
681251877Speter    serf_context_t *ctx,
682251877Speter    apr_socket_t *skt,
683251877Speter    serf_bucket_alloc_t *allocator);
684251877Speter
685251877Speter/**
686251877Speter * Create a bucket of type 'request bucket'.
687251877Speter * This is basically a wrapper around @a serf_bucket_request_create, which
688251877Speter * initializes the bucket using request, connection and/or context specific
689251877Speter * settings.
690251877Speter *
691251877Speter * This function will set following header(s):
692251877Speter * - Host: if the connection was created with @a serf_connection_create2.
693251877Speter */
694251877Speterserf_bucket_t *serf_request_bucket_request_create(
695251877Speter    serf_request_t *request,
696251877Speter    const char *method,
697251877Speter    const char *uri,
698251877Speter    serf_bucket_t *body,
699251877Speter    serf_bucket_alloc_t *allocator);
700251877Speter
701251877Speter/** @} */
702251877Speter
703251877Speter
704251877Speter/**
705251877Speter * @defgroup serf buckets
706251877Speter * @ingroup serf
707251877Speter * @{
708251877Speter */
709251877Speter
710251877Speter/** Pass as REQUESTED to the read function of a bucket to read, consume,
711251877Speter * and return all available data.
712251877Speter */
713251877Speter#define SERF_READ_ALL_AVAIL ((apr_size_t)-1)
714251877Speter
715251877Speter/** Acceptable newline types for bucket->readline(). */
716251877Speter#define SERF_NEWLINE_CR    0x0001
717251877Speter#define SERF_NEWLINE_CRLF  0x0002
718251877Speter#define SERF_NEWLINE_LF    0x0004
719251877Speter#define SERF_NEWLINE_ANY   0x0007
720251877Speter
721251877Speter/** Used to indicate that a newline is not present in the data buffer. */
722251877Speter/* ### should we make this zero? */
723251877Speter#define SERF_NEWLINE_NONE  0x0008
724251877Speter
725251877Speter/** Used to indicate that a CR was found at the end of a buffer, and CRLF
726251877Speter * was acceptable. It may be that the LF is present, but it needs to be
727251877Speter * read first.
728251877Speter *
729251877Speter * Note: an alternative to using this symbol would be for callers to see
730251877Speter * the SERF_NEWLINE_CR return value, and know that some "end of buffer" was
731251877Speter * reached. While this works well for @see serf_util_readline, it does not
732251877Speter * necessary work as well for buckets (there is no obvious "end of buffer",
733251877Speter * although there is an "end of bucket"). The other problem with that
734251877Speter * alternative is that developers might miss the condition. This symbol
735251877Speter * calls out the possibility and ensures that callers will watch for it.
736251877Speter */
737251877Speter#define SERF_NEWLINE_CRLF_SPLIT 0x0010
738251877Speter
739251877Speter
740251877Speterstruct serf_bucket_type_t {
741251877Speter
742251877Speter    /** name of this bucket type */
743251877Speter    const char *name;
744251877Speter
745251877Speter    /**
746251877Speter     * Read (and consume) up to @a requested bytes from @a bucket.
747251877Speter     *
748251877Speter     * A pointer to the data will be returned in @a data, and its length
749251877Speter     * is specified by @a len.
750251877Speter     *
751251877Speter     * The data will exist until one of two conditions occur:
752251877Speter     *
753251877Speter     * 1) this bucket is destroyed
754251877Speter     * 2) another call to any read function or to peek()
755251877Speter     *
756251877Speter     * If an application needs the data to exist for a longer duration,
757251877Speter     * then it must make a copy.
758251877Speter     */
759251877Speter    apr_status_t (*read)(serf_bucket_t *bucket, apr_size_t requested,
760251877Speter                         const char **data, apr_size_t *len);
761251877Speter
762251877Speter    /**
763251877Speter     * Read (and consume) a line of data from @a bucket.
764251877Speter     *
765251877Speter     * The acceptable forms of a newline are given by @a acceptable, and
766251877Speter     * the type found is returned in @a found. If a newline is not present
767251877Speter     * in the returned data, then SERF_NEWLINE_NONE is stored into @a found.
768251877Speter     *
769251877Speter     * A pointer to the data is returned in @a data, and its length is
770251877Speter     * specified by @a len. The data will include the newline, if present.
771251877Speter     *
772251877Speter     * Note that there is no way to limit the amount of data returned
773251877Speter     * by this function.
774251877Speter     *
775251877Speter     * The lifetime of the data is the same as that of the @see read
776251877Speter     * function above.
777251877Speter     */
778251877Speter    apr_status_t (*readline)(serf_bucket_t *bucket, int acceptable,
779251877Speter                             int *found,
780251877Speter                             const char **data, apr_size_t *len);
781251877Speter
782251877Speter    /**
783251877Speter     * Read a set of pointer/length pairs from the bucket.
784251877Speter     *
785251877Speter     * The size of the @a vecs array is specified by @a vecs_size. The
786251877Speter     * bucket should fill in elements of the array, and return the number
787251877Speter     * used in @a vecs_used.
788251877Speter     *
789251877Speter     * Each element of @a vecs should specify a pointer to a block of
790251877Speter     * data and a length of that data.
791251877Speter     *
792251877Speter     * The total length of all data elements should not exceed the
793251877Speter     * amount specified in @a requested.
794251877Speter     *
795251877Speter     * The lifetime of the data is the same as that of the @see read
796251877Speter     * function above.
797251877Speter     */
798251877Speter    apr_status_t (*read_iovec)(serf_bucket_t *bucket, apr_size_t requested,
799251877Speter                               int vecs_size, struct iovec *vecs,
800251877Speter                               int *vecs_used);
801251877Speter
802251877Speter    /**
803251877Speter     * Read data from the bucket in a form suitable for apr_socket_sendfile()
804251877Speter     *
805251877Speter     * On input, hdtr->numheaders and hdtr->numtrailers specify the size
806251877Speter     * of the hdtr->headers and hdtr->trailers arrays, respectively. The
807251877Speter     * bucket should fill in the headers and trailers, up to the specified
808251877Speter     * limits, and set numheaders and numtrailers to the number of iovecs
809251877Speter     * filled in for each item.
810251877Speter     *
811251877Speter     * @a file should be filled in with a file that can be read. If a file
812251877Speter     * is not available or appropriate, then NULL should be stored. The
813251877Speter     * file offset for the data should be stored in @a offset, and the
814251877Speter     * length of that data should be stored in @a len. If a file is not
815251877Speter     * returned, then @a offset and @a len should be ignored.
816251877Speter     *
817251877Speter     * The file position is not required to correspond to @a offset, and
818251877Speter     * the caller may manipulate it at will.
819251877Speter     *
820251877Speter     * The total length of all data elements, and the portion of the
821251877Speter     * file should not exceed the amount specified in @a requested.
822251877Speter     *
823251877Speter     * The lifetime of the data is the same as that of the @see read
824251877Speter     * function above.
825251877Speter     */
826251877Speter    apr_status_t (*read_for_sendfile)(serf_bucket_t *bucket,
827251877Speter                                      apr_size_t requested, apr_hdtr_t *hdtr,
828251877Speter                                      apr_file_t **file, apr_off_t *offset,
829251877Speter                                      apr_size_t *len);
830251877Speter
831251877Speter    /**
832251877Speter     * Look within @a bucket for a bucket of the given @a type. The bucket
833251877Speter     * must be the "initial" data because it will be consumed by this
834251877Speter     * function. If the given bucket type is available, then read and consume
835251877Speter     * it, and return it to the caller.
836251877Speter     *
837251877Speter     * This function is usually used by readers that have custom handling
838251877Speter     * for specific bucket types (e.g. looking for a file bucket to pass
839251877Speter     * to apr_socket_sendfile).
840251877Speter     *
841251877Speter     * If a bucket of the given type is not found, then NULL is returned.
842251877Speter     *
843251877Speter     * The returned bucket becomes the responsibility of the caller. When
844251877Speter     * the caller is done with the bucket, it should be destroyed.
845251877Speter     */
846251877Speter    serf_bucket_t * (*read_bucket)(serf_bucket_t *bucket,
847251877Speter                                   const serf_bucket_type_t *type);
848251877Speter
849251877Speter    /**
850251877Speter     * Peek, but don't consume, the data in @a bucket.
851251877Speter     *
852251877Speter     * Since this function is non-destructive, the implicit read size is
853251877Speter     * SERF_READ_ALL_AVAIL. The caller can then use whatever amount is
854251877Speter     * appropriate.
855251877Speter     *
856251877Speter     * The @a data parameter will point to the data, and @a len will
857251877Speter     * specify how much data is available. The lifetime of the data follows
858251877Speter     * the same rules as the @see read function above.
859251877Speter     *
860251877Speter     * Note: if the peek does not return enough data for your particular
861251877Speter     * use, then you must read/consume some first, then peek again.
862251877Speter     *
863251877Speter     * If the returned data represents all available data, then APR_EOF
864251877Speter     * will be returned. Since this function does not consume data, it
865251877Speter     * can return the same data repeatedly rather than blocking; thus,
866251877Speter     * APR_EAGAIN will never be returned.
867251877Speter     */
868251877Speter    apr_status_t (*peek)(serf_bucket_t *bucket,
869251877Speter                         const char **data, apr_size_t *len);
870251877Speter
871251877Speter    /**
872251877Speter     * Destroy @a bucket, along with any associated resources.
873251877Speter     */
874251877Speter    void (*destroy)(serf_bucket_t *bucket);
875251877Speter
876251877Speter    /* ### apr buckets have 'copy', 'split', and 'setaside' functions.
877251877Speter       ### not sure whether those will be needed in this bucket model.
878251877Speter    */
879251877Speter};
880251877Speter
881251877Speter/**
882251877Speter * Should the use and lifecycle of buckets be tracked?
883251877Speter *
884251877Speter * When tracking, the system will ensure several semantic requirements
885251877Speter * of bucket use:
886251877Speter *
887251877Speter *   - if a bucket returns APR_EAGAIN, one of its read functions should
888251877Speter *     not be called immediately. the context's run loop should be called.
889251877Speter *     ### and for APR_EOF, too?
890251877Speter *   - all buckets must be drained of input before returning to the
891251877Speter *     context's run loop.
892251877Speter *   - buckets should not be destroyed before they return APR_EOF unless
893251877Speter *     the connection is closed for some reason.
894251877Speter *
895251877Speter * Undefine this symbol to avoid the tracking (and a performance gain).
896251877Speter *
897251877Speter * ### we may want to examine when/how we provide this. should it always
898251877Speter * ### be compiled in? and apps select it before including this header?
899251877Speter */
900251877Speter/* #define SERF_DEBUG_BUCKET_USE */
901251877Speter
902251877Speter
903251877Speter/* Internal macros for tracking bucket use. */
904251877Speter#ifdef SERF_DEBUG_BUCKET_USE
905251877Speter#define SERF__RECREAD(b,s) serf_debug__record_read(b,s)
906251877Speter#else
907251877Speter#define SERF__RECREAD(b,s) (s)
908251877Speter#endif
909251877Speter
910251877Speter#define serf_bucket_read(b,r,d,l) SERF__RECREAD(b, (b)->type->read(b,r,d,l))
911251877Speter#define serf_bucket_readline(b,a,f,d,l) \
912251877Speter    SERF__RECREAD(b, (b)->type->readline(b,a,f,d,l))
913251877Speter#define serf_bucket_read_iovec(b,r,s,v,u) \
914251877Speter    SERF__RECREAD(b, (b)->type->read_iovec(b,r,s,v,u))
915251877Speter#define serf_bucket_read_for_sendfile(b,r,h,f,o,l) \
916251877Speter    SERF__RECREAD(b, (b)->type->read_for_sendfile(b,r,h,f,o,l))
917251877Speter#define serf_bucket_read_bucket(b,t) ((b)->type->read_bucket(b,t))
918251877Speter#define serf_bucket_peek(b,d,l) ((b)->type->peek(b,d,l))
919251877Speter#define serf_bucket_destroy(b) ((b)->type->destroy(b))
920251877Speter
921251877Speter/**
922251877Speter * Check whether a real error occurred. Note that bucket read functions
923251877Speter * can return EOF and EAGAIN as part of their "normal" operation, so they
924251877Speter * should not be considered an error.
925251877Speter */
926251877Speter#define SERF_BUCKET_READ_ERROR(status) ((status) \
927251877Speter                                        && !APR_STATUS_IS_EOF(status) \
928251877Speter                                        && !APR_STATUS_IS_EAGAIN(status) \
929251877Speter                                        && (SERF_ERROR_WAIT_CONN != status))
930251877Speter
931251877Speter
932251877Speterstruct serf_bucket_t {
933251877Speter
934251877Speter    /** the type of this bucket */
935251877Speter    const serf_bucket_type_t *type;
936251877Speter
937251877Speter    /** bucket-private data */
938251877Speter    void *data;
939251877Speter
940251877Speter    /** the allocator used for this bucket (needed at destroy time) */
941251877Speter    serf_bucket_alloc_t *allocator;
942251877Speter};
943251877Speter
944251877Speter
945251877Speter/**
946251877Speter * Generic macro to construct "is TYPE" macros.
947251877Speter */
948251877Speter#define SERF_BUCKET_CHECK(b, btype) ((b)->type == &serf_bucket_type_ ## btype)
949251877Speter
950251877Speter
951251877Speter/**
952251877Speter * Notification callback for a block that was not returned to the bucket
953251877Speter * allocator when its pool was destroyed.
954251877Speter *
955251877Speter * The block of memory is given by @a block. The baton provided when the
956251877Speter * allocator was constructed is passed as @a unfreed_baton.
957251877Speter */
958251877Spetertypedef void (*serf_unfreed_func_t)(
959251877Speter    void *unfreed_baton,
960251877Speter    void *block);
961251877Speter
962251877Speter/**
963251877Speter * Create a new allocator for buckets.
964251877Speter *
965251877Speter * All buckets are associated with a serf bucket allocator. This allocator
966251877Speter * will be created within @a pool and will be destroyed when that pool is
967251877Speter * cleared or destroyed.
968251877Speter *
969251877Speter * When the allocator is destroyed, if any allocations were not explicitly
970251877Speter * returned (by calling serf_bucket_mem_free), then the @a unfreed callback
971251877Speter * will be invoked for each block. @a unfreed_baton will be passed to the
972251877Speter * callback.
973251877Speter *
974251877Speter * If @a unfreed is NULL, then the library will invoke the abort() stdlib
975251877Speter * call. Any failure to return memory is a bug in the application, and an
976251877Speter * abort can assist with determining what kinds of memory were not freed.
977251877Speter */
978251877Speterserf_bucket_alloc_t *serf_bucket_allocator_create(
979251877Speter    apr_pool_t *pool,
980251877Speter    serf_unfreed_func_t unfreed,
981251877Speter    void *unfreed_baton);
982251877Speter
983251877Speter/**
984251877Speter * Return the pool that was used for this @a allocator.
985251877Speter *
986251877Speter * WARNING: the use of this pool for allocations requires a very
987251877Speter *   detailed understanding of pool behaviors, the bucket system,
988251877Speter *   and knowledge of the bucket's use within the overall pattern
989251877Speter *   of request/response behavior.
990251877Speter *
991251877Speter * See design-guide.txt for more information about pool usage.
992251877Speter */
993251877Speterapr_pool_t *serf_bucket_allocator_get_pool(
994251877Speter    const serf_bucket_alloc_t *allocator);
995251877Speter
996251877Speter
997251877Speter/**
998251877Speter * Utility structure for reading a complete line of input from a bucket.
999251877Speter *
1000251877Speter * Since it is entirely possible for a line to be broken by APR_EAGAIN,
1001251877Speter * this structure can be used to accumulate the data until a complete line
1002251877Speter * has been read from a bucket.
1003251877Speter */
1004251877Speter
1005251877Speter/* This limit applies to the line buffer functions. If an application needs
1006251877Speter * longer lines, then they will need to manually handle line buffering.
1007251877Speter */
1008251877Speter#define SERF_LINEBUF_LIMIT 8000
1009251877Speter
1010251877Spetertypedef struct {
1011251877Speter
1012251877Speter    /* Current state of the buffer. */
1013251877Speter    enum {
1014251877Speter        SERF_LINEBUF_EMPTY,
1015251877Speter        SERF_LINEBUF_READY,
1016251877Speter        SERF_LINEBUF_PARTIAL,
1017251877Speter        SERF_LINEBUF_CRLF_SPLIT
1018251877Speter    } state;
1019251877Speter
1020251877Speter    /* How much of the buffer have we used? */
1021251877Speter    apr_size_t used;
1022251877Speter
1023251877Speter    /* The line is read into this buffer, minus CR/LF */
1024251877Speter    char line[SERF_LINEBUF_LIMIT];
1025251877Speter
1026251877Speter} serf_linebuf_t;
1027251877Speter
1028251877Speter/**
1029251877Speter * Initialize the @a linebuf structure.
1030251877Speter */
1031251877Spetervoid serf_linebuf_init(serf_linebuf_t *linebuf);
1032251877Speter
1033251877Speter/**
1034251877Speter * Fetch a line of text from @a bucket, accumulating the line into
1035251877Speter * @a linebuf. @a acceptable specifies the types of newlines which are
1036251877Speter * acceptable for this fetch.
1037251877Speter *
1038251877Speter * ### we should return a data/len pair so that we can avoid a copy,
1039251877Speter * ### rather than having callers look into our state and line buffer.
1040251877Speter */
1041251877Speterapr_status_t serf_linebuf_fetch(
1042251877Speter    serf_linebuf_t *linebuf,
1043251877Speter    serf_bucket_t *bucket,
1044251877Speter    int acceptable);
1045251877Speter
1046251877Speter/** @} */
1047251877Speter
1048251877Speter
1049251877Speter/* Internal functions for bucket use and lifecycle tracking */
1050251877Speterapr_status_t serf_debug__record_read(
1051251877Speter    const serf_bucket_t *bucket,
1052251877Speter    apr_status_t status);
1053251877Spetervoid serf_debug__entered_loop(
1054251877Speter    serf_bucket_alloc_t *allocator);
1055251877Spetervoid serf_debug__closed_conn(
1056251877Speter    serf_bucket_alloc_t *allocator);
1057251877Spetervoid serf_debug__bucket_destroy(
1058251877Speter    const serf_bucket_t *bucket);
1059251877Spetervoid serf_debug__bucket_alloc_check(
1060251877Speter    serf_bucket_alloc_t *allocator);
1061251877Speter
1062251877Speter/* Version info */
1063251877Speter#define SERF_MAJOR_VERSION 1
1064253895Speter#define SERF_MINOR_VERSION 3
1065289166Speter#define SERF_PATCH_VERSION 8
1066251877Speter
1067251877Speter/* Version number string */
1068251877Speter#define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
1069251877Speter                            APR_STRINGIFY(SERF_MINOR_VERSION) "." \
1070251877Speter                            APR_STRINGIFY(SERF_PATCH_VERSION)
1071251877Speter
1072251877Speter/**
1073251877Speter * Check at compile time if the Serf version is at least a certain
1074251877Speter * level.
1075251877Speter * @param major The major version component of the version checked
1076251877Speter * for (e.g., the "1" of "1.3.0").
1077251877Speter * @param minor The minor version component of the version checked
1078251877Speter * for (e.g., the "3" of "1.3.0").
1079251877Speter * @param patch The patch level component of the version checked
1080251877Speter * for (e.g., the "0" of "1.3.0").
1081251877Speter */
1082251877Speter#define SERF_VERSION_AT_LEAST(major,minor,patch)                         \
1083251877Speter(((major) < SERF_MAJOR_VERSION)                                          \
1084251877Speter  || ((major) == SERF_MAJOR_VERSION && (minor) < SERF_MINOR_VERSION)     \
1085251877Speter   || ((major) == SERF_MAJOR_VERSION && (minor) == SERF_MINOR_VERSION && \
1086251877Speter            (patch) <= SERF_PATCH_VERSION))
1087251877Speter
1088251877Speter
1089251877Speter/**
1090251877Speter * Returns the version of the library the application has linked/loaded.
1091251877Speter * Values are returned in @a major, @a minor, and @a patch.
1092251877Speter *
1093251877Speter * Applications will want to use this function to verify compatibility,
1094251877Speter * expecially while serf has not reached a 1.0 milestone. APIs and
1095251877Speter * semantics may change drastically until the library hits 1.0.
1096251877Speter */
1097251877Spetervoid serf_lib_version(
1098251877Speter    int *major,
1099251877Speter    int *minor,
1100251877Speter    int *patch);
1101251877Speter
1102251877Speter
1103251877Speter#ifdef __cplusplus
1104251877Speter}
1105251877Speter#endif
1106251877Speter
1107251877Speter
1108251877Speter/*
1109251877Speter * Every user of serf will want to deal with our various bucket types.
1110251877Speter * Go ahead and include that header right now.
1111251877Speter *
1112251877Speter * Note: make sure this occurs outside of the C++ namespace block
1113251877Speter */
1114251877Speter#include "serf_bucket_types.h"
1115251877Speter
1116251877Speter
1117251877Speter#endif    /* !SERF_H */
1118