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