| /* ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| */ |
| |
| #ifndef SERF_H |
| #define SERF_H |
| |
| /** |
| * @file serf.h |
| * @brief Main serf header file |
| */ |
| |
| #include <apr.h> |
| #include <apr_errno.h> |
| #include <apr_allocator.h> |
| #include <apr_pools.h> |
| #include <apr_network_io.h> |
| #include <apr_time.h> |
| #include <apr_poll.h> |
| #include <apr_uri.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* Forward declare some structures */ |
| typedef struct serf_context_t serf_context_t; |
| |
| typedef struct serf_bucket_t serf_bucket_t; |
| typedef struct serf_bucket_type_t serf_bucket_type_t; |
| typedef struct serf_bucket_alloc_t serf_bucket_alloc_t; |
| |
| typedef struct serf_connection_t serf_connection_t; |
| typedef struct serf_listener_t serf_listener_t; |
| typedef struct serf_incoming_t serf_incoming_t; |
| typedef struct serf_incoming_request_t serf_incoming_request_t; |
| |
| typedef struct serf_request_t serf_request_t; |
| |
| #if 0 |
| typedef struct serf_connection_type_t serf_connection_type_t; |
| typedef struct serf_protocol_t serf_protocol_t; |
| typedef struct serf_protocol_type_t serf_protocol_type_t; |
| #endif /* Connection and protocol API v2 */ |
| |
| typedef struct serf_config_t serf_config_t; |
| |
| /** |
| * @defgroup serf high-level constructs |
| * @ingroup serf |
| * @{ |
| */ |
| |
| /** |
| * Serf-specific error codes |
| */ |
| #define SERF_ERROR_RANGE 100 |
| #define SERF_ERROR_START (APR_OS_START_USERERR + SERF_ERROR_RANGE) |
| |
| /* This code is for when this is the last response on this connection: |
| * i.e. do not send any more requests on this connection or expect |
| * any more responses. |
| */ |
| #define SERF_ERROR_CLOSING (SERF_ERROR_START + 1) |
| /* This code is for when the connection terminated before the request |
| * could be processed on the other side. |
| */ |
| #define SERF_ERROR_REQUEST_LOST (SERF_ERROR_START + 2) |
| /* This code is for when the connection is blocked - we can not proceed |
| * until something happens - generally due to SSL negotiation-like behavior |
| * where a write() is blocked until a read() is processed. |
| */ |
| #define SERF_ERROR_WAIT_CONN (SERF_ERROR_START + 3) |
| /* This code is for when something went wrong during deflating compressed |
| * data e.g. a CRC error. */ |
| #define SERF_ERROR_DECOMPRESSION_FAILED (SERF_ERROR_START + 4) |
| /* This code is for when a response received from a http server is not in |
| * http-compliant syntax. */ |
| #define SERF_ERROR_BAD_HTTP_RESPONSE (SERF_ERROR_START + 5) |
| /* The server sent less data than what was announced. */ |
| #define SERF_ERROR_TRUNCATED_HTTP_RESPONSE (SERF_ERROR_START + 6) |
| /* The proxy server returned an error while setting up the SSL tunnel. */ |
| #define SERF_ERROR_SSLTUNNEL_SETUP_FAILED (SERF_ERROR_START + 7) |
| /* The server unexpectedly closed the connection prematurely. */ |
| #define SERF_ERROR_ABORTED_CONNECTION (SERF_ERROR_START + 8) |
| /* Generic 'The line too long'. Used internally. */ |
| #define SERF_ERROR_LINE_TOO_LONG (SERF_ERROR_START + 9) |
| /* The HTTP response status line too long. */ |
| #define SERF_ERROR_STATUS_LINE_TOO_LONG (SERF_ERROR_START + 10) |
| /* The HTTP response header too long. */ |
| #define SERF_ERROR_RESPONSE_HEADER_TOO_LONG (SERF_ERROR_START + 11) |
| /* The connection to the server timed out. */ |
| #define SERF_ERROR_CONNECTION_TIMEDOUT (SERF_ERROR_START + 12) |
| /* The stream returned less data than was expected */ |
| #define SERF_ERROR_TRUNCATED_STREAM (SERF_ERROR_START + 13) |
| /* The stream is empty */ |
| #define SERF_ERROR_EMPTY_STREAM (SERF_ERROR_START + 14) |
| /* An empty read was returned. */ |
| #define SERF_ERROR_EMPTY_READ (SERF_ERROR_START + 15) |
| |
| /* Http-2 stream errors, mapped into our error range */ |
| #define SERF_ERROR_HTTP2_NO_ERROR (SERF_ERROR_START + 50) |
| #define SERF_ERROR_HTTP2_PROTOCOL_ERROR (SERF_ERROR_START + 51) |
| #define SERF_ERROR_HTTP2_INTERNAL_ERROR (SERF_ERROR_START + 52) |
| #define SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR (SERF_ERROR_START + 53) |
| #define SERF_ERROR_HTTP2_SETTINGS_TIMEOUT (SERF_ERROR_START + 54) |
| #define SERF_ERROR_HTTP2_STREAM_CLOSED (SERF_ERROR_START + 55) |
| #define SERF_ERROR_HTTP2_FRAME_SIZE_ERROR (SERF_ERROR_START + 56) |
| #define SERF_ERROR_HTTP2_REFUSED_STREAM (SERF_ERROR_START + 57) |
| #define SERF_ERROR_HTTP2_CANCEL (SERF_ERROR_START + 58) |
| #define SERF_ERROR_HTTP2_COMPRESSION_ERROR (SERF_ERROR_START + 59) |
| #define SERF_ERROR_HTTP2_CONNECT_ERROR (SERF_ERROR_START + 60) |
| #define SERF_ERROR_HTTP2_ENHANCE_YOUR_CALM (SERF_ERROR_START + 61) |
| #define SERF_ERROR_HTTP2_INADEQUATE_SECURITY (SERF_ERROR_START + 62) |
| #define SERF_ERROR_HTTP2_HTTP_1_1_REQUIRED (SERF_ERROR_START + 63) |
| |
| /* SSL certificates related errors */ |
| #define SERF_ERROR_SSL_CERT_FAILED (SERF_ERROR_START + 70) |
| |
| /* SSL communications related errors */ |
| #define SERF_ERROR_SSL_COMM_FAILED (SERF_ERROR_START + 71) |
| |
| /* SSL handshake failed */ |
| #define SERF_ERROR_SSL_SETUP_FAILED (SERF_ERROR_START + 72) |
| |
| /* Serf-internal error code, raised when the server initiates SSL renegotiation |
| on a connection that uses HTTP pipelining. */ |
| #define SERF_ERROR_SSL_NEGOTIATE_IN_PROGRESS (SERF_ERROR_START + 73) |
| |
| /* General authentication related errors */ |
| #define SERF_ERROR_AUTHN_FAILED (SERF_ERROR_START + 90) |
| |
| /* None of the available authn mechanisms for the request are supported */ |
| #define SERF_ERROR_AUTHN_NOT_SUPPORTED (SERF_ERROR_START + 91) |
| |
| /* Authn was requested by the server but the header lacked some attribute */ |
| #define SERF_ERROR_AUTHN_MISSING_ATTRIBUTE (SERF_ERROR_START + 92) |
| |
| /* Authentication handler initialization related errors */ |
| #define SERF_ERROR_AUTHN_INITALIZATION_FAILED (SERF_ERROR_START + 93) |
| |
| /* The user credentials were rejected by the server */ |
| #define SERF_ERROR_AUTHN_CREDENTIALS_REJECTED (SERF_ERROR_START + 94) |
| |
| /* Error code reserved for use in the test suite. */ |
| #define SERF_ERROR_ISSUE_IN_TESTSUITE (SERF_ERROR_START + 99) |
| |
| /* This macro groups errors potentially raised when reading a http response. */ |
| #define SERF_BAD_RESPONSE_ERROR(status) ((status) \ |
| && ((SERF_ERROR_DECOMPRESSION_FAILED == (status)) \ |
| ||(SERF_ERROR_BAD_HTTP_RESPONSE == (status)) \ |
| ||(SERF_ERROR_TRUNCATED_HTTP_RESPONSE == (status)))) |
| |
| /** |
| * Return a string that describes the specified error code. |
| * |
| * If the error code is not one of the above Serf error codes, then |
| * NULL will be returned. |
| * |
| * Note regarding lifetime: the string is a statically-allocated constant |
| */ |
| const char *serf_error_string(apr_status_t errcode); |
| |
| |
| /** |
| * Create a new context for serf operations. |
| * |
| * A serf context defines a control loop which processes multiple |
| * connections simultaneously. |
| * |
| * The context will be allocated within @a pool. |
| */ |
| serf_context_t *serf_context_create( |
| apr_pool_t *pool); |
| |
| /** |
| * Callback function. Add a socket to the externally managed poll set. |
| * |
| * Both @a pfd and @a serf_baton should be used when calling serf_event_trigger |
| * later. |
| */ |
| typedef apr_status_t (*serf_socket_add_t)( |
| void *user_baton, |
| apr_pollfd_t *pfd, |
| void *serf_baton); |
| |
| /** |
| * Callback function. Remove the socket, identified by both @a pfd and |
| * @a serf_baton from the externally managed poll set. |
| */ |
| typedef apr_status_t (*serf_socket_remove_t)( |
| void *user_baton, |
| apr_pollfd_t *pfd, |
| void *serf_baton); |
| |
| /* Create a new context for serf operations. |
| * |
| * Use this function to make serf not use its internal control loop, but |
| * instead rely on an external event loop. Serf will use the @a addf and @a rmf |
| * callbacks to notify of any event on a connection. The @a user_baton will be |
| * passed through the addf and rmf callbacks. |
| * |
| * The context will be allocated within @a pool. |
| */ |
| serf_context_t *serf_context_create_ex( |
| void *user_baton, |
| serf_socket_add_t addf, |
| serf_socket_remove_t rmf, |
| apr_pool_t *pool); |
| |
| /** |
| * Make serf process events on a connection, identified by both @a pfd and |
| * @a serf_baton. |
| * |
| * Any outbound data is delivered, and incoming data is made available to |
| * the associated response handlers and their buckets. |
| * |
| * If any data is processed (incoming or outgoing), then this function will |
| * return with APR_SUCCESS. |
| */ |
| apr_status_t serf_event_trigger( |
| serf_context_t *s, |
| void *serf_baton, |
| const apr_pollfd_t *pfd); |
| |
| /** @see serf_context_run should not block at all. */ |
| #define SERF_DURATION_NOBLOCK 0 |
| /** @see serf_context_run should run for (nearly) "forever". */ |
| #define SERF_DURATION_FOREVER 2000000000 /* approx 1^31 */ |
| |
| /** |
| * Run the main networking control loop. |
| * |
| * The set of connections defined by the serf context @a ctx are processed. |
| * Any outbound data is delivered, and incoming data is made available to |
| * the associated response handlers and their buckets. This function will |
| * block on the network for no longer than @a duration microseconds. |
| * |
| * If any data is processed (incoming or outgoing), then this function will |
| * return with APR_SUCCESS. Typically, the caller will just want to call it |
| * again to continue processing data. |
| * |
| * If no activity occurs within the specified timeout duration, then |
| * APR_TIMEUP is returned. |
| * |
| * All temporary allocations will be made in @a pool. |
| */ |
| apr_status_t serf_context_run( |
| serf_context_t *ctx, |
| apr_short_interval_time_t duration, |
| apr_pool_t *pool); |
| |
| |
| apr_status_t serf_context_prerun( |
| serf_context_t *ctx); |
| |
| /** |
| * Callback function for progress information. @a progress indicates cumulative |
| * number of bytes read or written, for the whole context. |
| */ |
| typedef void (*serf_progress_t)( |
| void *progress_baton, |
| apr_off_t read, |
| apr_off_t write); |
| |
| /** |
| * Sets the progress callback function. @a progress_func will be called every |
| * time bytes are read of or written on a socket. |
| */ |
| void serf_context_set_progress_cb( |
| serf_context_t *ctx, |
| const serf_progress_t progress_func, |
| void *progress_baton); |
| |
| /** @} */ |
| |
| /** |
| * @defgroup serf connections and requests |
| * @ingroup serf |
| * @{ |
| */ |
| |
| /** |
| * When a connection is established, the application needs to wrap some |
| * buckets around @a skt to enable serf to process incoming responses. This |
| * is the control point for assembling connection-level processing logic |
| * around the given socket. |
| * |
| * The @a setup_baton is the baton established at connection creation time. |
| * |
| * This callback corresponds to reading from the server. Since this is an |
| * on-demand activity, we use a callback. The corresponding write operation |
| * is based on the @see serf_request_deliver function, where the application |
| * can assemble the appropriate bucket(s) before delivery. |
| * |
| * The returned bucket should live at least as long as the connection itself. |
| * It is assumed that an appropriate allocator is passed in @a setup_baton. |
| * ### we may want to create a connection-level allocator and pass that |
| * ### along. however, that allocator would *only* be used for this |
| * ### callback. it may be wasteful to create a per-conn allocator, so this |
| * ### baton-based, app-responsible form might be best. |
| * |
| * Responsibility for the buckets is passed to the serf library. They will be |
| * destroyed when the connection is closed. |
| * |
| * All temporary allocations should be made in @a pool. |
| */ |
| typedef apr_status_t (*serf_connection_setup_t)( |
| apr_socket_t *skt, |
| serf_bucket_t **read_bkt, |
| serf_bucket_t **write_bkt, |
| void *setup_baton, |
| apr_pool_t *pool); |
| |
| /** |
| * ### need to update docco w.r.t socket. became "stream" recently. |
| * ### the stream does not have a barrier, this callback should generally |
| * ### add a barrier around the stream before incorporating it into a |
| * ### response bucket stack. |
| * ### should serf add the barrier automatically to protect its data |
| * ### structure? i.e. the passed bucket becomes owned rather than |
| * ### borrowed. that might suit overall semantics better. |
| * Accept an incoming response for @a request, and its @a socket. A bucket |
| * for the response should be constructed and returned. This is the control |
| * point for assembling the appropriate wrapper buckets around the socket to |
| * enable processing of the incoming response. |
| * |
| * The @a acceptor_baton is the baton provided when the specified request |
| * was created. |
| * |
| * The request's pool and bucket allocator should be used for any allocations |
| * that need to live for the duration of the response. Care should be taken |
| * to bound the amount of memory stored in this pool -- to ensure that |
| * allocations are not proportional to the amount of data in the response. |
| * |
| * Responsibility for the bucket is passed to the serf library. It will be |
| * destroyed when the response has been fully read (the bucket returns an |
| * APR_EOF status from its read functions). |
| * |
| * All temporary allocations should be made in @a pool. |
| */ |
| /* ### do we need to return an error? */ |
| typedef serf_bucket_t * (*serf_response_acceptor_t)( |
| serf_request_t *request, |
| serf_bucket_t *stream, |
| void *acceptor_baton, |
| apr_pool_t *pool); |
| |
| /** |
| * Notification callback for when a connection closes. |
| * |
| * This callback is used to inform an application that the @a conn |
| * connection has been (abnormally) closed. The @a closed_baton is the |
| * baton provided when the connection was first opened. The reason for |
| * closure is given in @a why, and will be APR_SUCCESS if the application |
| * requested closure (by clearing the pool used to allocate this |
| * connection or calling serf_connection_close). |
| * |
| * All temporary allocations should be made in @a pool. |
| */ |
| typedef void (*serf_connection_closed_t)( |
| serf_connection_t *conn, |
| void *closed_baton, |
| apr_status_t why, |
| apr_pool_t *pool); |
| |
| /** |
| * Like serf_connection_closed_t, but applies to incoming connections. |
| */ |
| typedef apr_status_t (*serf_incoming_closed_t)( |
| serf_incoming_t *incoming, |
| void *closed_baton, |
| apr_status_t why, |
| apr_pool_t *pool); |
| |
| /** |
| * Response data has arrived and should be processed. |
| * |
| * Whenever response data for @a request arrives (initially, or continued data |
| * arrival), this handler is invoked. The response data is available in the |
| * @a response bucket. The @a handler_baton is passed along from the baton |
| * provided by the request setup callback (@see serf_request_setup_t). |
| * |
| * The handler MUST process data from the @a response bucket until the |
| * bucket's read function states it would block (see APR_STATUS_IS_EAGAIN). |
| * The handler is invoked only when new data arrives. If no further data |
| * arrives, and the handler does not process all available data, then the |
| * system can result in a deadlock around the unprocessed, but read, data. |
| * |
| * The handler should return APR_EOF when the response has been fully read. |
| * If calling the handler again would block, APR_EAGAIN should be returned. |
| * If the handler should be invoked again, simply return APR_SUCCESS. |
| * |
| * Note: if the connection closed (at the request of the application, or |
| * because of an (abnormal) termination) while a request is being delivered, |
| * or before a response arrives, then @a response will be NULL. This is the |
| * signal that the request was not delivered properly, and no further |
| * response should be expected (this callback will not be invoked again). |
| * If a request is injected into the connection (during this callback's |
| * execution, or otherwise), then the connection will be reopened. |
| * |
| * All temporary allocations should be made in @a pool. |
| */ |
| typedef apr_status_t (*serf_response_handler_t)( |
| serf_request_t *request, |
| serf_bucket_t *response, |
| void *handler_baton, |
| apr_pool_t *pool); |
| |
| /** |
| * Callback function to be implemented by the application, so that serf |
| * can handle server and proxy authentication. |
| * code = 401 (server) or 407 (proxy). |
| * baton = the baton passed to serf_context_run. |
| * authn_type = one of "Basic", "Digest". |
| */ |
| typedef apr_status_t (*serf_credentials_callback_t)( |
| char **username, |
| char **password, |
| serf_request_t *request, void *baton, |
| int code, const char *authn_type, |
| const char *realm, |
| apr_pool_t *pool); |
| |
| /** |
| * Create a new connection associated with the @a ctx serf context. |
| * |
| * If no proxy server is configured, a connection will be created to |
| * (eventually) connect to the address specified by @a address. The address must |
| * live at least as long as @a pool (thus, as long as the connection object). |
| * If a proxy server is configured, @address will be ignored. |
| * |
| * The connection object will be allocated within @a pool. Clearing or |
| * destroying this pool will close the connection, and terminate any |
| * outstanding requests or responses. |
| * |
| * When the connection is closed (upon request or because of an error), |
| * then the @a closed callback is invoked, and @a closed_baton is passed. |
| * |
| * ### doc on setup(_baton). tweak below comment re: acceptor. |
| * NULL may be passed for @a acceptor and @a closed; default implementations |
| * will be used. |
| * |
| * Note: the connection is not made immediately. It will be opened on |
| * the next call to @see serf_context_run. |
| */ |
| serf_connection_t *serf_connection_create( |
| serf_context_t *ctx, |
| apr_sockaddr_t *address, |
| serf_connection_setup_t setup, |
| void *setup_baton, |
| serf_connection_closed_t closed, |
| void *closed_baton, |
| apr_pool_t *pool); |
| |
| /** |
| * Create a new connection associated with the @a ctx serf context. |
| * |
| * A connection will be created to (eventually) connect to the address |
| * specified by @a address. The address must live at least as long as |
| * @a pool (thus, as long as the connection object). |
| * |
| * The host address will be looked up based on the hostname in @a host_info. |
| * |
| * The connection object will be allocated within @a pool. Clearing or |
| * destroying this pool will close the connection, and terminate any |
| * outstanding requests or responses. |
| * |
| * When the connection is closed (upon request or because of an error), |
| * then the @a closed callback is invoked, and @a closed_baton is passed. |
| * |
| * ### doc on setup(_baton). tweak below comment re: acceptor. |
| * NULL may be passed for @a acceptor and @a closed; default implementations |
| * will be used. |
| * |
| * Note: the connection is not made immediately. It will be opened on |
| * the next call to @see serf_context_run. |
| */ |
| apr_status_t serf_connection_create2( |
| serf_connection_t **conn, |
| serf_context_t *ctx, |
| apr_uri_t host_info, |
| serf_connection_setup_t setup, |
| void *setup_baton, |
| serf_connection_closed_t closed, |
| void *closed_baton, |
| apr_pool_t *pool); |
| |
| |
| typedef apr_status_t (*serf_accept_client_t)( |
| serf_context_t *ctx, |
| serf_listener_t *l, |
| void *accept_baton, |
| apr_socket_t *insock, |
| apr_pool_t *pool); |
| |
| apr_status_t serf_listener_create( |
| serf_listener_t **listener, |
| serf_context_t *ctx, |
| const char *host, |
| apr_uint16_t port, |
| void *accept_baton, |
| serf_accept_client_t accept_func, |
| apr_pool_t *pool); |
| |
| typedef apr_status_t (*serf_incoming_request_handler_t)( |
| serf_incoming_request_t *req, |
| serf_bucket_t *request, |
| void *handler_baton, |
| apr_pool_t *pool); |
| |
| typedef apr_status_t (*serf_incoming_response_setup_t)( |
| serf_bucket_t **resp_bkt, |
| serf_incoming_request_t *req, |
| void *setup_baton, |
| serf_bucket_alloc_t *allocator, |
| apr_pool_t *pool); |
| |
| typedef apr_status_t (*serf_incoming_request_setup_t)( |
| serf_bucket_t **req_bkt, |
| serf_bucket_t *stream, |
| serf_incoming_request_t *req, |
| void *request_baton, |
| serf_incoming_request_handler_t *handler, |
| void **handler_baton, |
| serf_incoming_response_setup_t *response_setup, |
| void **response_setup_baton, |
| apr_pool_t *pool); |
| |
| /* ### Deprecated: can't do anything with request */ |
| typedef apr_status_t(*serf_incoming_request_cb_t)( |
| serf_context_t *ctx, |
| serf_incoming_request_t *req, |
| void *request_baton, |
| apr_pool_t *pool); |
| |
| /* ### Deprecated: Misses ssl support and actual |
| request handling. */ |
| apr_status_t serf_incoming_create( |
| serf_incoming_t **client, |
| serf_context_t *ctx, |
| apr_socket_t *insock, |
| void *request_baton, |
| serf_incoming_request_cb_t request, |
| apr_pool_t *pool); |
| |
| /** |
| * Creates a new client associated with @a ctx for socket @a insock. The client |
| * takes responsibility for @a client_pool and will destroy it after the |
| * connection is closed. Typically this would be the same pool as where the |
| * incomming socket @a insock is allocated in. |
| * |
| * This non-standard behavior is needed to support listeners inside the same |
| * @a ctx instance without leaking memory for each used connections. Callers |
| * might want to create a specific client pool if they use a non-standard |
| * listening pattern. |
| * |
| * Once the connection is setup @a setup will be called with @a setup_baton |
| * to setup the connection's bucket support. |
| * |
| * When the connection closed @a closed will be called with @a closed_baton to |
| * notify that the client and its pool are about to be destroyed. |
| * |
| * Once the connection is fully setup incoming requests will be routed to @a |
| * req_setup with @a req_setup_baton, to handle processing. |
| * |
| * @since New in 1.4. |
| */ |
| apr_status_t serf_incoming_create2( |
| serf_incoming_t **client, |
| serf_context_t *ctx, |
| apr_socket_t *insock, |
| serf_connection_setup_t setup, |
| void *setup_baton, |
| serf_incoming_closed_t closed, |
| void *closed_baton, |
| serf_incoming_request_setup_t req_setup, |
| void *req_setup_baton, |
| apr_pool_t *client_pool); |
| |
| /* Allows creating a response before the request is completely |
| read. Will call the response create function if it hasn't |
| been called yet. */ |
| apr_status_t serf_incoming_response_create( |
| serf_incoming_request_t *request); |
| |
| /** |
| * Reset the connection, but re-open the socket again. |
| */ |
| apr_status_t serf_connection_reset( |
| serf_connection_t *conn); |
| |
| /** |
| * Close the connection associated with @a conn and cancel all pending requests. |
| * |
| * The closed callback passed to serf_connection_create() will be invoked |
| * with APR_SUCCESS. |
| */ |
| apr_status_t serf_connection_close( |
| serf_connection_t *conn); |
| |
| /** |
| * Sets the maximum number of outstanding requests @a max_requests on the |
| * connection @a conn. Setting max_requests to 0 means unlimited (the default). |
| * Ex.: setting max_requests to 1 means a request is sent when a response on the |
| * previous request was received and handled. |
| * |
| * In general, serf tends to take around 16KB per outstanding request. |
| */ |
| void serf_connection_set_max_outstanding_requests( |
| serf_connection_t *conn, |
| unsigned int max_requests); |
| |
| void serf_connection_set_async_responses( |
| serf_connection_t *conn, |
| serf_response_acceptor_t acceptor, |
| void *acceptor_baton, |
| serf_response_handler_t handler, |
| void *handler_baton); |
| |
| typedef enum serf_connection_framing_type_t { |
| SERF_CONNECTION_FRAMING_TYPE_NONE = 0, |
| SERF_CONNECTION_FRAMING_TYPE_HTTP1, |
| SERF_CONNECTION_FRAMING_TYPE_HTTP2, |
| SERF_CONNECTION_FRAMING_TYPE_FCGI |
| } serf_connection_framing_type_t; |
| |
| /** |
| * Sets the connection framing on the connection to the specified type. The |
| * NONE type specifies that the framing type is undetermined yet and no |
| * requests should be written to the connection until the framing type is |
| * set. Connections default to HTTP1 framing. |
| * |
| * @since New in 1.4. |
| */ |
| void serf_connection_set_framing_type( |
| serf_connection_t *conn, |
| serf_connection_framing_type_t framing_type); |
| |
| /** |
| * @since New in 1.4. |
| */ |
| void serf_incoming_set_framing_type( |
| serf_incoming_t *client, |
| serf_connection_framing_type_t framing_type); |
| |
| /** |
| * Setup the @a request for delivery on its connection. |
| * |
| * Right before this is invoked, @a pool will be built within the |
| * connection's pool for the request to use. The associated response will |
| * be allocated within that subpool. An associated bucket allocator will |
| * be built. These items may be fetched from the request object through |
| * @see serf_request_get_pool or @see serf_request_get_alloc. |
| * |
| * The content of the request is specified by the @a req_bkt bucket. When |
| * a response arrives, the @a acceptor callback will be invoked (along with |
| * the @a acceptor_baton) to produce a response bucket. That bucket will then |
| * be passed to @a handler, along with the @a handler_baton. |
| * |
| * The responsibility for the request bucket is passed to the request |
| * object. When the request is done with the bucket, it will be destroyed. |
| */ |
| typedef apr_status_t (*serf_request_setup_t)( |
| serf_request_t *request, |
| void *setup_baton, |
| serf_bucket_t **req_bkt, |
| serf_response_acceptor_t *acceptor, |
| void **acceptor_baton, |
| serf_response_handler_t *handler, |
| void **handler_baton, |
| apr_pool_t *pool); |
| |
| /** |
| * Construct a request object for the @a conn connection. |
| * |
| * When it is time to deliver the request, the @a setup callback will |
| * be invoked with the @a setup_baton passed into it to complete the |
| * construction of the request object. |
| * |
| * If the request has not (yet) been delivered, then it may be canceled |
| * with @see serf_request_cancel. |
| * |
| * Invoking any calls other than @see serf_request_cancel before the setup |
| * callback executes is not supported. |
| */ |
| serf_request_t *serf_connection_request_create( |
| serf_connection_t *conn, |
| serf_request_setup_t setup, |
| void *setup_baton); |
| |
| /** |
| * Construct a request object for the @a conn connection, add it in the |
| * list as the next to-be-written request before all unwritten requests. |
| * |
| * When it is time to deliver the request, the @a setup callback will |
| * be invoked with the @a setup_baton passed into it to complete the |
| * construction of the request object. |
| * |
| * If the request has not (yet) been delivered, then it may be canceled |
| * with @see serf_request_cancel. |
| * |
| * Invoking any calls other than @see serf_request_cancel before the setup |
| * callback executes is not supported. |
| */ |
| serf_request_t *serf_connection_priority_request_create( |
| serf_connection_t *conn, |
| serf_request_setup_t setup, |
| void *setup_baton); |
| |
| /** The default request priority */ |
| #define SERF_REQUEST_PRIORITY_DEFAULT 0x1000 |
| |
| /** |
| * Updates the request's priority information. Some protocol implementations, |
| * such as HTTP/2 may use this information for response scheduling. The |
| * actual behavior depends on the server, intermediate proxies and of course |
| * the protocol implementation. |
| * |
| * It is recommended to prioritize a request before sending it to the server, |
| * as that avoids race conditions and receiving unwanted results. |
| * |
| * If @a depends_on is set, then the request is marked as dependent on |
| * @a depends_on, and the result of @a request will only be received if |
| * no progress can be made on @a depends_on itself. |
| * |
| * @a priority is used to relatively prioritize multiple dependencies on the |
| * same target. Passing 0 will keep the original priority. In case of HTTP/2 |
| * this value is mapped to a 8 bit value by ignoring the lowest 8 bits. |
| * |
| * By default a request is created at priority SERF_REQUEST_PRIORITY_DEFAULT. |
| * |
| * If @a exclusive is set to TRUE, then all existing dependencies on @a |
| * depends_on will be updated to now depend on @a request, to make @a |
| * request the only dependency of @a request. When FALSE, request will just |
| * be added as a dependency. |
| * |
| * @since New in 1.4. |
| */ |
| void serf_connection_request_prioritize(serf_request_t *request, |
| serf_request_t *depends_on, |
| apr_uint16_t priority, |
| int exclusive); |
| |
| /** Returns detected network latency for the @a conn connection. Negative |
| * value means that latency is unknwon. |
| */ |
| apr_interval_time_t serf_connection_get_latency(serf_connection_t *conn); |
| |
| /** |
| * Returns the number of requests waiting to be sent over connection CONN. |
| */ |
| unsigned int serf_connection_queued_requests(serf_connection_t *conn); |
| |
| /** |
| * Returns the total number of requests for which a response hasn't been |
| * received yet on connection CONN. This includes requests: |
| * - that are queued but not sent. |
| * - that have been sent but no response has been completely received yet. |
| */ |
| unsigned int serf_connection_pending_requests(serf_connection_t *conn); |
| |
| /** Check if a @a request has been completely written. |
| * |
| * Returns APR_SUCCESS if the request was written completely on the connection. |
| * Returns APR_EBUSY if the request is not yet or partially written. |
| */ |
| apr_status_t serf_request_is_written( |
| serf_request_t *request); |
| |
| /** |
| * Cancel the request specified by the @a request object. |
| * |
| * If the request has been scheduled for delivery, then its response |
| * handler will be run, passing NULL for the response bucket. |
| * |
| * If the request has already been (partially or fully) delivered, then |
| * APR_EBUSY is returned and the request is *NOT* canceled. To properly |
| * cancel the request, the connection must be closed (by clearing or |
| * destroying its associated pool). |
| */ |
| apr_status_t serf_request_cancel( |
| serf_request_t *request); |
| |
| /** |
| * Return the pool associated with @a request. |
| * |
| * WARNING: be very careful about the kinds of things placed into this |
| * pool. In particular, all allocation should be bounded in size, rather |
| * than proportional to any data stream. |
| */ |
| apr_pool_t *serf_request_get_pool( |
| const serf_request_t *request); |
| |
| /** |
| * Return the bucket allocator associated with @a request. |
| */ |
| serf_bucket_alloc_t *serf_request_get_alloc( |
| const serf_request_t *request); |
| |
| /** |
| * Return the connection associated with @a request. |
| */ |
| serf_connection_t *serf_request_get_conn( |
| const serf_request_t *request); |
| |
| /** |
| * Update the @a handler and @a handler_baton for this @a request. |
| * |
| * This can be called after the request has started processing - |
| * subsequent data will be delivered to this new handler. |
| */ |
| void serf_request_set_handler( |
| serf_request_t *request, |
| const serf_response_handler_t handler, |
| const void **handler_baton); |
| |
| /** |
| * Configure proxy server settings, to be used by all connections associated |
| * with the @a ctx serf context. |
| * |
| * The next connection will be created to connect to the proxy server |
| * specified by @a address. The address must live at least as long as the |
| * serf context. |
| */ |
| void serf_config_proxy( |
| serf_context_t *ctx, |
| apr_sockaddr_t *address); |
| |
| /* Supported authentication types. */ |
| #define SERF_AUTHN_NONE 0x00 |
| #define SERF_AUTHN_BASIC 0x01 |
| #define SERF_AUTHN_DIGEST 0x02 |
| #define SERF_AUTHN_NTLM 0x04 |
| #define SERF_AUTHN_NEGOTIATE 0x08 |
| #define SERF_AUTHN_ALL 0xFF |
| |
| /** |
| * Define the authentication handlers that serf will try on incoming requests. |
| */ |
| void serf_config_authn_types( |
| serf_context_t *ctx, |
| int authn_types); |
| |
| /** |
| * Set the credentials callback handler. |
| */ |
| void serf_config_credentials_callback( |
| serf_context_t *ctx, |
| serf_credentials_callback_t cred_cb); |
| |
| /* ### maybe some connection control functions for flood? */ |
| |
| /*** Special bucket creation functions ***/ |
| |
| /** |
| * Create a bucket of type 'socket bucket'. |
| * This is basically a wrapper around @a serf_bucket_socket_create, which |
| * initializes the bucket using connection and/or context specific settings. |
| */ |
| serf_bucket_t *serf_context_bucket_socket_create( |
| serf_context_t *ctx, |
| apr_socket_t *skt, |
| serf_bucket_alloc_t *allocator); |
| |
| /** |
| * Create a bucket of type 'request bucket'. |
| * This is basically a wrapper around @a serf_bucket_request_create, which |
| * initializes the bucket using request, connection and/or context specific |
| * settings. |
| * |
| * This function will set following header(s): |
| * - Host: if the connection was created with @a serf_connection_create2. |
| */ |
| serf_bucket_t *serf_request_bucket_request_create( |
| serf_request_t *request, |
| const char *method, |
| const char *uri, |
| serf_bucket_t *body, |
| serf_bucket_alloc_t *allocator); |
| |
| /** @} */ |
| |
| |
| /** |
| * @defgroup serf buckets |
| * @ingroup serf |
| * @{ |
| */ |
| |
| /** Pass as REQUESTED to the read function of a bucket to read, consume, |
| * and return all available data. |
| */ |
| #define SERF_READ_ALL_AVAIL ((apr_size_t)-1) |
| |
| /** Acceptable newline types for bucket->readline(). */ |
| #define SERF_NEWLINE_CR 0x0001 |
| #define SERF_NEWLINE_CRLF 0x0002 |
| #define SERF_NEWLINE_LF 0x0004 |
| #define SERF_NEWLINE_ANY 0x0007 |
| |
| /** Used to indicate that a newline is not present in the data buffer. */ |
| /* ### should we make this zero? */ |
| #define SERF_NEWLINE_NONE 0x0008 |
| |
| /** Used to indicate that a CR was found at the end of a buffer, and CRLF |
| * was acceptable. It may be that the LF is present, but it needs to be |
| * read first. |
| * |
| * Note: an alternative to using this symbol would be for callers to see |
| * the SERF_NEWLINE_CR return value, and know that some "end of buffer" was |
| * reached. While this works well for @see serf_util_readline, it does not |
| * necessary work as well for buckets (there is no obvious "end of buffer", |
| * although there is an "end of bucket"). The other problem with that |
| * alternative is that developers might miss the condition. This symbol |
| * calls out the possibility and ensures that callers will watch for it. |
| */ |
| #define SERF_NEWLINE_CRLF_SPLIT 0x0010 |
| |
| /** Used to indicate that length of remaining data in bucket is unknown. See |
| * serf_bucket_type_t->get_remaining(). |
| */ |
| #define SERF_LENGTH_UNKNOWN ((apr_uint64_t) -1) |
| |
| struct serf_bucket_type_t { |
| |
| /** name of this bucket type */ |
| const char *name; |
| |
| /** |
| * Read (and consume) up to @a requested bytes from @a bucket. |
| * |
| * A pointer to the data will be returned in @a data, and its length |
| * is specified by @a len. |
| * |
| * The data will exist until one of two conditions occur: |
| * |
| * 1) this bucket is destroyed |
| * 2) another call to any read function, get_remaining() or to peek() |
| * |
| * If an application needs the data to exist for a longer duration, |
| * then it must make a copy. |
| */ |
| apr_status_t (*read)(serf_bucket_t *bucket, apr_size_t requested, |
| const char **data, apr_size_t *len); |
| |
| /** |
| * Read (and consume) a line of data from @a bucket. |
| * |
| * The acceptable forms of a newline are given by @a acceptable, and |
| * the type found is returned in @a found. If a newline is not present |
| * in the returned data, then SERF_NEWLINE_NONE is stored into @a found. |
| * |
| * A pointer to the data is returned in @a data, and its length is |
| * specified by @a len. The data will include the newline, if present. |
| * |
| * Note that there is no way to limit the amount of data returned |
| * by this function. @see serf_bucket_limited_readline(). |
| * |
| * The lifetime of the data is the same as that of the @see read |
| * function above. |
| */ |
| apr_status_t (*readline)(serf_bucket_t *bucket, int acceptable, |
| int *found, |
| const char **data, apr_size_t *len); |
| |
| /** |
| * Read a set of pointer/length pairs from the bucket. |
| * |
| * The size of the @a vecs array is specified by @a vecs_size. The |
| * bucket should fill in elements of the array, and return the number |
| * used in @a vecs_used. |
| * |
| * Each element of @a vecs should specify a pointer to a block of |
| * data and a length of that data. |
| * |
| * The total length of all data elements should not exceed the |
| * amount specified in @a requested. |
| * |
| * The lifetime of the data is the same as that of the @see read |
| * function above. |
| */ |
| apr_status_t (*read_iovec)(serf_bucket_t *bucket, apr_size_t requested, |
| int vecs_size, struct iovec *vecs, |
| int *vecs_used); |
| |
| /** |
| * Read data from the bucket in a form suitable for apr_socket_sendfile() |
| * |
| * On input, hdtr->numheaders and hdtr->numtrailers specify the size |
| * of the hdtr->headers and hdtr->trailers arrays, respectively. The |
| * bucket should fill in the headers and trailers, up to the specified |
| * limits, and set numheaders and numtrailers to the number of iovecs |
| * filled in for each item. |
| * |
| * @a file should be filled in with a file that can be read. If a file |
| * is not available or appropriate, then NULL should be stored. The |
| * file offset for the data should be stored in @a offset, and the |
| * length of that data should be stored in @a len. If a file is not |
| * returned, then @a offset and @a len should be ignored. |
| * |
| * The file position is not required to correspond to @a offset, and |
| * the caller may manipulate it at will. |
| * |
| * The total length of all data elements, and the portion of the |
| * file should not exceed the amount specified in @a requested. |
| * |
| * The lifetime of the data is the same as that of the @see read |
| * function above. |
| */ |
| apr_status_t (*read_for_sendfile)(serf_bucket_t *bucket, |
| apr_size_t requested, apr_hdtr_t *hdtr, |
| apr_file_t **file, apr_off_t *offset, |
| apr_size_t *len); |
| |
| /** |
| * Look within @a bucket for a bucket of the given @a type. The bucket |
| * must be the "initial" data because it will be consumed by this |
| * function. If the given bucket type is available, then read and consume |
| * it, and return it to the caller. |
| * |
| * This function is usually used by readers that have custom handling |
| * for specific bucket types (e.g. looking for a file bucket to pass |
| * to apr_socket_sendfile). |
| * |
| * If a bucket of the given type is not found, then NULL is returned. |
| * |
| * The returned bucket becomes the responsibility of the caller. When |
| * the caller is done with the bucket, it should be destroyed. |
| */ |
| serf_bucket_t * (*read_bucket)(serf_bucket_t *bucket, |
| const serf_bucket_type_t *type); |
| |
| /** |
| * Peek, but don't consume, the data in @a bucket. |
| * |
| * Since this function is non-destructive, the implicit read size is |
| * SERF_READ_ALL_AVAIL. The caller can then use whatever amount is |
| * appropriate. |
| * |
| * The @a data parameter will point to the data, and @a len will |
| * specify how much data is available. The lifetime of the data follows |
| * the same rules as the @see read function above. |
| * |
| * Note: if the peek does not return enough data for your particular |
| * use, then you must read/consume some first, then peek again. |
| * |
| * If the returned data represents all available data, then APR_EOF |
| * will be returned. Since this function does not consume data, it |
| * can return the same data repeatedly rather than blocking; thus, |
| * APR_EAGAIN will never be returned. |
| */ |
| apr_status_t (*peek)(serf_bucket_t *bucket, |
| const char **data, apr_size_t *len); |
| |
| /** |
| * Destroy @a bucket, along with any associated resources. |
| */ |
| void (*destroy)(serf_bucket_t *bucket); |
| |
| /* The following members are valid only if read_bucket equals to |
| * serf_buckets_are_v2() (or in a future spec _v3, etc.). */ |
| |
| /* Real pointer to read_bucket() method when read_bucket is |
| * serf_buckets_are_v2(). |
| * |
| * @since New in 1.4 / Buckets v2. |
| */ |
| serf_bucket_t * (*read_bucket_v2)(serf_bucket_t *bucket, |
| const serf_bucket_type_t *type); |
| |
| /* Returns length of remaining data to be read in @a bucket. Returns |
| * SERF_LENGTH_UNKNOWN if length is unknown. |
| * |
| * @since New in 1.4 / Buckets v2. |
| */ |
| apr_uint64_t (*get_remaining)(serf_bucket_t *bucket); |
| |
| /* Provides a reference to a config object containing all configuration |
| * values relevant for this bucket. |
| * |
| * @since New in 1.4 / Buckets v2 |
| */ |
| apr_status_t (*set_config)(serf_bucket_t *bucket, serf_config_t *config); |
| |
| /* ### apr buckets have 'copy', 'split', and 'setaside' functions. |
| ### not sure whether those will be needed in this bucket model. |
| */ |
| }; |
| |
| /** |
| * Should the use and lifecycle of buckets be tracked? |
| * |
| * When tracking, the system will ensure several semantic requirements |
| * of bucket use: |
| * |
| * - if a bucket returns APR_EAGAIN, one of its read functions should |
| * not be called immediately. the context's run loop should be called. |
| * ### and for APR_EOF, too? |
| * - all buckets must be drained of input before returning to the |
| * context's run loop. |
| * - buckets should not be destroyed before they return APR_EOF unless |
| * the connection is closed for some reason. |
| * |
| * Undefine this symbol to avoid the tracking (and a performance gain). |
| * |
| * ### we may want to examine when/how we provide this. should it always |
| * ### be compiled in? and apps select it before including this header? |
| */ |
| /* #define SERF_DEBUG_BUCKET_USE */ |
| |
| /* Predefined value for read_bucket vtable member to declare v2 buckets |
| * vtable. |
| * |
| * @since New in 1.4. |
| */ |
| serf_bucket_t * serf_buckets_are_v2(serf_bucket_t *bucket, |
| const serf_bucket_type_t *type); |
| |
| /** Gets the serf bucket type of the bucket if the bucket implements at least |
| * buckets version, or if not a bucket type providing a default implementation |
| * |
| * @since New in 1.4. |
| */ |
| const serf_bucket_type_t *serf_get_type(serf_bucket_t *bucket, |
| int min_version); |
| |
| /* Internal macros for tracking bucket use. */ |
| #ifdef SERF_DEBUG_BUCKET_USE |
| #define SERF__RECREAD(b,s) serf_debug__record_read(b,s) |
| #else |
| #define SERF__RECREAD(b,s) (s) |
| #endif |
| |
| #define serf_bucket_read(b,r,d,l) SERF__RECREAD(b, (b)->type->read(b,r,d,l)) |
| #define serf_bucket_readline(b,a,f,d,l) \ |
| SERF__RECREAD(b, (b)->type->readline(b,a,f,d,l)) |
| #define serf_bucket_read_iovec(b,r,s,v,u) \ |
| SERF__RECREAD(b, (b)->type->read_iovec(b,r,s,v,u)) |
| #define serf_bucket_read_for_sendfile(b,r,h,f,o,l) \ |
| SERF__RECREAD(b, (b)->type->read_for_sendfile(b,r,h,f,o,l)) |
| #define serf_bucket_read_bucket(b,t) ((b)->type->read_bucket(b,t)) |
| #define serf_bucket_peek(b,d,l) ((b)->type->peek(b,d,l)) |
| #define serf_bucket_destroy(b) ((b)->type->destroy(b)) |
| #define serf_bucket_get_remaining(b) (serf_get_type(b, 2)->get_remaining(b)) |
| #define serf_bucket_set_config(b,c) (serf_get_type(b, 2)->set_config(b, c)) |
| |
| /** |
| * Check whether a real error occurred. Note that bucket read functions |
| * can return EOF and EAGAIN as part of their "normal" operation, so they |
| * should not be considered an error. |
| */ |
| #define SERF_BUCKET_READ_ERROR(status) ((status) \ |
| && !APR_STATUS_IS_EOF(status) \ |
| && !APR_STATUS_IS_EAGAIN(status) \ |
| && (SERF_ERROR_WAIT_CONN != status)) |
| |
| |
| struct serf_bucket_t { |
| |
| /** the type of this bucket */ |
| const serf_bucket_type_t *type; |
| |
| /** bucket-private data */ |
| void *data; |
| |
| /** the allocator used for this bucket (needed at destroy time) */ |
| serf_bucket_alloc_t *allocator; |
| }; |
| |
| |
| /** |
| * Generic macro to construct "is TYPE" macros. |
| */ |
| #define SERF_BUCKET_CHECK(b, btype) ((b)->type == &serf_bucket_type_ ## btype) |
| |
| |
| /** @} */ |
| |
| |
| /** |
| * Notification callback for a block that was not returned to the bucket |
| * allocator when its pool was destroyed. |
| * |
| * The block of memory is given by @a block. The baton provided when the |
| * allocator was constructed is passed as @a unfreed_baton. |
| */ |
| typedef void (*serf_unfreed_func_t)( |
| void *unfreed_baton, |
| void *block); |
| |
| /** |
| * Create a new allocator for buckets. |
| * |
| * All buckets are associated with a serf bucket allocator. This allocator |
| * will be created within @a pool and will be destroyed when that pool is |
| * cleared or destroyed. |
| * |
| * When the allocator is destroyed, if any allocations were not explicitly |
| * returned (by calling serf_bucket_mem_free), then the @a unfreed callback |
| * will be invoked for each block. @a unfreed_baton will be passed to the |
| * callback. |
| * |
| * If @a unfreed is NULL, then the library will invoke the abort() stdlib |
| * call. Any failure to return memory is a bug in the application, and an |
| * abort can assist with determining what kinds of memory were not freed. |
| */ |
| serf_bucket_alloc_t *serf_bucket_allocator_create( |
| apr_pool_t *pool, |
| serf_unfreed_func_t unfreed, |
| void *unfreed_baton); |
| |
| /** |
| * Return the pool that was used for this @a allocator. |
| * |
| * WARNING: the use of this pool for allocations requires a very |
| * detailed understanding of pool behaviors, the bucket system, |
| * and knowledge of the bucket's use within the overall pattern |
| * of request/response behavior. |
| * |
| * See design-guide.txt for more information about pool usage. |
| */ |
| apr_pool_t *serf_bucket_allocator_get_pool( |
| const serf_bucket_alloc_t *allocator); |
| |
| |
| /** |
| * Utility structure for reading a complete line of input from a bucket. |
| * |
| * Since it is entirely possible for a line to be broken by APR_EAGAIN, |
| * this structure can be used to accumulate the data until a complete line |
| * has been read from a bucket. |
| */ |
| |
| /* This limit applies to the line buffer functions. If an application needs |
| * longer lines, then they will need to manually handle line buffering. |
| */ |
| #define SERF_LINEBUF_LIMIT 8000 |
| |
| typedef struct serf_linebuf_t { |
| |
| /* Current state of the buffer. */ |
| enum { |
| SERF_LINEBUF_EMPTY, |
| SERF_LINEBUF_READY, |
| SERF_LINEBUF_PARTIAL, |
| SERF_LINEBUF_CRLF_SPLIT |
| } state; |
| |
| /* How much of the buffer have we used? */ |
| apr_size_t used; |
| |
| /* The line is read into this buffer, minus CR/LF. |
| * |
| * NOTE: Before serf 2.0 buffer IS NOT NUL terminated |
| * and @a used should be used to find line length. |
| * |
| * Since serf 2.0 buffer is always NUL terminated. |
| **/ |
| char line[SERF_LINEBUF_LIMIT]; |
| |
| } serf_linebuf_t; |
| |
| /** |
| * Initialize the @a linebuf structure. |
| */ |
| void serf_linebuf_init(serf_linebuf_t *linebuf); |
| |
| /** |
| * Fetch a line of text from @a bucket, accumulating the line into |
| * @a linebuf. @a acceptable specifies the types of newlines which are |
| * acceptable for this fetch. |
| * |
| * ### we should return a data/len pair so that we can avoid a copy, |
| * ### rather than having callers look into our state and line buffer. |
| */ |
| apr_status_t serf_linebuf_fetch( |
| serf_linebuf_t *linebuf, |
| serf_bucket_t *bucket, |
| int acceptable); |
| |
| /*** Configuration store declarations ***/ |
| |
| typedef const apr_uint32_t serf_config_key_t; |
| |
| /* The left-most byte of the int32 key holds the category (bit flags). |
| The other bytes are a number representing the key. |
| |
| Serf will not use the second byte for its own keys, so applications can |
| use this byte to define custom keys. |
| */ |
| typedef enum serf_config_categories_t { |
| SERF_CONFIG_PER_CONTEXT = 0x10000000, |
| SERF_CONFIG_PER_HOST = 0x20000000, |
| SERF_CONFIG_PER_CONNECTION = 0x40000000, |
| } serf_config_categories_t; |
| |
| #define SERF_CONFIG_HOST_NAME (SERF_CONFIG_PER_HOST | 0x000001) |
| #define SERF_CONFIG_HOST_PORT (SERF_CONFIG_PER_HOST | 0x000002) |
| #define SERF_CONFIG_CONN_LOCALIP (SERF_CONFIG_PER_CONNECTION | 0x000001) |
| #define SERF_CONFIG_CONN_REMOTEIP (SERF_CONFIG_PER_CONNECTION | 0x000002) |
| #define SERF_CONFIG_CONN_PIPELINING (SERF_CONFIG_PER_CONNECTION | 0x000003) |
| #define SERF_CONFIG_CTX_LOGBATON (SERF_CONFIG_PER_CONTEXT | 0x000001) |
| |
| /* Configuration values stored in the configuration store: |
| |
| Category Key Value Type |
| -------- --- ---------- |
| Context logbaton log_baton_t * |
| Context proxyauthn apr_hash_t * (not implemented) |
| Connection localip const char * |
| Connection remoteip const char * |
| Host hostname const char * |
| Host hostport const char * |
| Host authn apr_hash_t * (not implemented) |
| */ |
| |
| /* Set a value of type const char * for configuration item CATEGORY+KEY. |
| @since New in 1.4. |
| */ |
| apr_status_t serf_config_set_string(serf_config_t *config, |
| serf_config_key_t key, |
| const char *value); |
| /* Copy a value of type const char * and set it for configuration item |
| CATEGORY+KEY. |
| @since New in 1.4. |
| */ |
| apr_status_t serf_config_set_stringc(serf_config_t *config, |
| serf_config_key_t key, |
| const char *value); |
| |
| /* Set a value of generic type for configuration item CATEGORY+KEY. |
| See @a serf_set_config_string for COPY_FLAGS description. |
| @since New in 1.4. |
| */ |
| apr_status_t serf_config_set_stringf(serf_config_t *config, |
| serf_config_key_t key, |
| const char *fmt, ...); |
| |
| /* Set a value of generic type for configuration item CATEGORY+KEY. |
| See @a serf_set_config_string for COPY_FLAGS description. |
| @since New in 1.4. |
| */ |
| apr_status_t serf_config_set_object(serf_config_t *config, |
| serf_config_key_t key, |
| void *value); |
| |
| /* Get the value for configuration item CATEGORY+KEY. The value's type will |
| be fixed, see the above table. |
| Returns APR_EINVAL when getting a key from a category that this config |
| object doesn't contain, APR_SUCCESS otherwise. |
| @since New in 1.4. |
| */ |
| apr_status_t serf_config_get_string(serf_config_t *config, |
| serf_config_key_t key, |
| const char **value); |
| |
| apr_status_t serf_config_get_object(serf_config_t *config, |
| serf_config_key_t key, |
| void **value); |
| |
| /* Remove the value for configuration item CATEGORY+KEY from the configuration |
| store. |
| @since New in 1.4. |
| */ |
| apr_status_t serf_config_remove_value(serf_config_t *config, |
| serf_config_key_t key); |
| |
| /*** Serf logging API ***/ |
| |
| /* Ordered list of log levels, more detailed log levels include less |
| detailed levels. (e.g. level DEBUG also logs ERROR, WARNING & INFO messages). |
| */ |
| #define SERF_LOG_ERROR 0x0001 |
| #define SERF_LOG_WARNING 0x0002 |
| #define SERF_LOG_INFO 0x0004 |
| #define SERF_LOG_DEBUG 0x0008 |
| #define SERF_LOG_NONE 0x0000 |
| |
| /* List of components, used as a mask. */ |
| #define SERF_LOGCOMP_ALL_MSG 0xFFFF /* All components, including message |
| content */ |
| #define SERF_LOGCOMP_RAWMSG 0x0100 /* logs requests and responses directly on |
| the socket layer. */ |
| #define SERF_LOGCOMP_SSLMSG 0x0200 /* logs decrypted requests and responses. */ |
| |
| #define SERF_LOGCOMP_ALL 0x00FF /* All components, no message content */ |
| #define SERF_LOGCOMP_SSL 0x0001 /* The SSL component */ |
| #define SERF_LOGCOMP_AUTHN 0x0002 /* Authentication components */ |
| #define SERF_LOGCOMP_CONN 0x0004 /* Connection-related events */ |
| #define SERF_LOGCOMP_COMPR 0x0008 /* The compression (deflate) component */ |
| #define SERF_LOGCOMP_PROTOCOL 0x0010 /* The protocol components */ |
| #define SERF_LOGCOMP_NONE 0x0000 |
| |
| typedef struct serf_log_output_t serf_log_output_t; |
| typedef struct serf_log_layout_t serf_log_layout_t; |
| |
| /* The default log layout. It's format is: |
| [TIMESTAMP] [LOG LEVEL] [l:LOCALIP:PORT r:REMOTEIP:PORT] FILENAME MESSAGE |
| */ |
| #define SERF_LOG_DEFAULT_LAYOUT ((serf_log_layout_t *)NULL) |
| |
| /* TODO: it's not yet possible to define custom layouts */ |
| |
| /* Create a stream output for log info. This can be used with one of the |
| standard streams stderr or stdout. |
| LAYOUT should be SERF_LOG_DEFAULT_LAYOUT (there's no alternative for now). |
| The lifetime of POOL should be atleast the same as that of CTX, but it can |
| be used by multiple contexts. */ |
| apr_status_t serf_logging_create_stream_output(serf_log_output_t **output, |
| serf_context_t *ctx, |
| apr_uint32_t level, |
| apr_uint32_t comp_mask, |
| serf_log_layout_t *layout, |
| FILE *fp, |
| apr_pool_t *pool); |
| |
| /* Define an output handler for a log level and a (set of) log component(s). |
| OUTPUT is the object returned by one of the serf_logging_create_XXX_output |
| factory functions. */ |
| apr_status_t serf_logging_add_output(serf_context_t *ctx, |
| const serf_log_output_t *output); |
| |
| |
| /*** Connection and protocol API v2 ***/ |
| #if 0 |
| /* ### docco. */ |
| apr_status_t serf_connection_switch_protocol( |
| serf_connection_t *conn, |
| serf_protocol_t *proto |
| /* ### other params? */ |
| ); |
| |
| |
| /* ### docco. */ |
| typedef struct serf_queue_item_t serf_queue_item_t; |
| |
| |
| /** |
| * Present a response to the application. |
| * |
| * Called when a response has been processed by the current protocol (to any |
| * extent necessary) and is ready for the application to handle. |
| * |
| * Note: @a request may be NULL if this response is server-pushed rather than |
| * specifically requested. |
| */ |
| typedef apr_status_t (*serf_begin_response_t)( |
| /* ### args not settled */ |
| void **handler_baton, |
| serf_request_t *request, |
| serf_bucket_t *response, |
| apr_pool_t *scratch_pool); |
| |
| |
| /* ### better name? */ |
| typedef apr_status_t (*serf_handler_t)( |
| /* ### args not settled */ |
| void *handler_baton, |
| serf_bucket_t *response, |
| apr_pool_t *scratch_pool); |
| |
| |
| struct serf_protocol_type_t { |
| /** Name of this protocol type. */ |
| const char *name; |
| |
| /** Vtable version. */ |
| int version; |
| #define SERF_PROTOCOL_TYPE_VERSION 1 |
| |
| /** |
| * When a pending request reaches the front of the queue, then it becomes |
| * "active". This callback is used to build/provide the protocol-specific |
| * request bucket. |
| * |
| * ### more docco |
| */ |
| apr_status_t (*serf_request_activate_t)( |
| serf_bucket_t **request_bkt, |
| serf_queue_item_t *request_qi, |
| void *request_baton, |
| serf_bucket_alloc_t *request_bktalloc, |
| apr_pool_t *scratch_pool); |
| |
| /** |
| * Construct a protocol parsing bucket, for passing to the process_data |
| * vtable entry. |
| * |
| * When data arrives on the connection, and a parser is not already |
| * processing the connection's data, then build a new bucket to parse |
| * this incoming data (according to the protocol). |
| */ |
| serf_bucket_t * (*build_parser)(serf_protocol_t *proto, |
| apr_pool_t *scratch_pool); |
| |
| /** |
| * The protocol should parse all available response data, per the protocol. |
| * |
| * This is called when data has become available to the parser. The protocol |
| * should read all available data before returning. |
| */ |
| apr_status_t (*process_data)(serf_protocol_t *proto, |
| serf_bucket_t *parser, |
| apr_pool_t *scratch_pool); |
| }; |
| |
| |
| /** |
| * Activate an HTTP request when it reaches the front of the queue. |
| * |
| * ### more docco |
| */ |
| typedef apr_status_t (*serf_http_activate_t)( |
| serf_bucket_t **body_bkt, |
| serf_bucket_t *request_bkt, /* type REQUEST */ |
| serf_queue_item_t *request_qi, |
| void *request_baton, |
| serf_bucket_alloc_t *request_bktalloc, |
| apr_pool_t *scratch_pool); |
| |
| |
| /** |
| * Create a new connection and associated HTTP protocol parser. |
| * |
| * The new connection/protocol will be associated with @a ctx. It will be |
| * opened once a request is placed into its outgoing queue. The connection |
| * will use @a hostname and @a port for the origin server. If |
| * @a proxy_hostname is not NULL, then all requests will go through the |
| * proxy specified by @a proxy_hostname and @a proxy_port. |
| * |
| * DNS lookups for @a hostname and @a proxy_hostname will be performed |
| * when the connection first opened, then cached in case the connection |
| * ever needs to be re-opened. |
| * |
| * When a queued request reaches the front of the queue, and is ready for |
| * delivery, then @a activate_cb will be called to prepare the request. |
| * |
| * @a authn_types specifies the types of authentication allowed on this |
| * connection. Normally, it should be SERF_AUTHN_ALL. When authentication |
| * credentials are required (for the origin server or the proxy), then |
| * @a creds_cb will be called with @a app_baton. |
| * |
| * When the connection is closed (upon request or because of an error), |
| * then @a closed_cb will be called with @a app_baton. |
| * |
| * The connection and protocol paresr will be allocated in @a result_pool. |
| * This function will use @a scratch_pool for temporary allocations. |
| */ |
| apr_status_t serf_http_protocol_create( |
| serf_protocol_t **proto, |
| serf_context_t *ctx, |
| const char *hostname, |
| int port, |
| const char *proxy_hostname, |
| int proxy_port, |
| int authn_types, |
| serf_http_activate_t activate_cb, |
| /* ### do we need different params for CREDS_CB and CLOSED_CB ? */ |
| serf_credentials_callback_t creds_cb, |
| serf_connection_closed_t closed_cb, |
| void *app_baton, |
| apr_pool_t *result_pool, |
| apr_pool_t *scratch_pool); |
| |
| |
| /* ### docco. create http proto parser with an encrypted connection. */ |
| apr_status_t serf_https_protocol_create( |
| serf_protocol_t **proto, |
| serf_context_t *ctx, |
| const char *hostname, |
| int port, |
| /* ### client certs, credential validation callbacks, etc */ |
| serf_connection_closed_t closed, |
| void *closed_baton, |
| apr_pool_t *result_pool, |
| apr_pool_t *scratch_pool); |
| |
| |
| /* ### docco. queue up an http request. */ |
| serf_queue_item_t *serf_http_request_queue( |
| serf_protocol_t *proto, |
| int priority, |
| void *request_baton); |
| |
| /** |
| * ### rationalize against "serf connections and request" group above |
| * |
| * @defgroup serf connections |
| * @ingroup serf |
| * @{ |
| */ |
| |
| struct serf_connection_type_t { |
| /** Name of this connection type. */ |
| const char *name; |
| |
| /** Vtable version. */ |
| int version; |
| #define SERF_CONNECTION_TYPE_VERSION 1 |
| |
| /** |
| * Initiate a connection to the server. |
| * |
| * ### docco. note async. note that request(s) may be queued. |
| * ### can we somehow defer the SSL tunnel's CONNECT to the higher |
| * ### layer? then have the HTTP protocol layer wrap a CONN_PLAIN |
| * ### into a CONN_TLS connection once the tunnel is established? |
| */ |
| apr_status_t (*connect)(serf_connection_t *conn); |
| |
| /** |
| * Returns a bucket for reading from this connection. |
| * |
| * This bucket remains constant for the lifetime of the connection. It has |
| * built-in BARRIER bucket protection, so it can safely be "destroyed" |
| * without problem (and a later call to this vtable function will return |
| * the same bucket again). |
| * |
| * For all intents and purposes, this bucket is borrowed by the caller. |
| * |
| * This bucket effectively maps to the underlying socket, or possibly to |
| * a decrypting bucket layered over the socket. |
| */ |
| serf_bucket_t * (*get_read_bucket)(serf_connection_t *conn); |
| |
| /** |
| * Write some data into into the connection. |
| * |
| * Attempt to write a number of iovecs into the connection. The number of |
| * vectors *completely* written will be returned in @a vecs_written. If that |
| * equals @a vecs_size, then @a last_written will be set to 0. If it is less |
| * (not all iovecs were written), then the amount written from the next, |
| * incompletely written iovec is returned in @a last_written. |
| * |
| * In other words, the first byte of unwritten content is located at: |
| * |
| * <pre> |
| * first = vecs[vecs_written][last_written]; |
| * </pre> |
| * |
| * If all bytes are written, then APR_SUCCESS is returned. If only a portion |
| * was written, then APR_EAGAIN will be returned. |
| */ |
| apr_status_t (*writev)(serf_connection_t *conn, |
| int vecs_size, struct iovec *vecs, |
| int *vecs_written, apr_size_t *last_written); |
| }; |
| |
| #endif /* Connection and protocol API v2 */ |
| /** @} */ |
| |
| |
| /* Internal functions for bucket use and lifecycle tracking */ |
| apr_status_t serf_debug__record_read( |
| const serf_bucket_t *bucket, |
| apr_status_t status); |
| void serf_debug__entered_loop( |
| serf_bucket_alloc_t *allocator); |
| void serf_debug__closed_conn( |
| serf_bucket_alloc_t *allocator); |
| void serf_debug__bucket_destroy( |
| const serf_bucket_t *bucket); |
| void serf_debug__bucket_alloc_check( |
| serf_bucket_alloc_t *allocator); |
| |
| /* Version info */ |
| #define SERF_MAJOR_VERSION 2 |
| #define SERF_MINOR_VERSION 0 |
| #define SERF_PATCH_VERSION 0 |
| |
| /* Version number string */ |
| #define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \ |
| APR_STRINGIFY(SERF_MINOR_VERSION) "." \ |
| APR_STRINGIFY(SERF_PATCH_VERSION) |
| |
| /** |
| * Check at compile time if the Serf version is at least a certain |
| * level. |
| * @param major The major version component of the version checked |
| * for (e.g., the "1" of "1.3.0"). |
| * @param minor The minor version component of the version checked |
| * for (e.g., the "3" of "1.3.0"). |
| * @param patch The patch level component of the version checked |
| * for (e.g., the "0" of "1.3.0"). |
| */ |
| #define SERF_VERSION_AT_LEAST(major,minor,patch) \ |
| (((major) < SERF_MAJOR_VERSION) \ |
| || ((major) == SERF_MAJOR_VERSION && (minor) < SERF_MINOR_VERSION) \ |
| || ((major) == SERF_MAJOR_VERSION && (minor) == SERF_MINOR_VERSION && \ |
| (patch) <= SERF_PATCH_VERSION)) |
| |
| |
| /** |
| * Returns the version of the library the application has linked/loaded. |
| * Values are returned in @a major, @a minor, and @a patch. |
| * |
| * Applications will want to use this function to verify compatibility, |
| * expecially while serf has not reached a 1.0 milestone. APIs and |
| * semantics may change drastically until the library hits 1.0. |
| */ |
| void serf_lib_version( |
| int *major, |
| int *minor, |
| int *patch); |
| |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| |
| /* |
| * Every user of serf will want to deal with our various bucket types. |
| * Go ahead and include that header right now. |
| * |
| * Note: make sure this occurs outside of the C++ namespace block |
| */ |
| #include "serf_bucket_types.h" |
| |
| |
| #endif /* !SERF_H */ |