404 lines
12 KiB
C
404 lines
12 KiB
C
|
/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
|
||
|
*
|
||
|
* Licensed 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_PRIVATE_H_
|
||
|
#define _SERF_PRIVATE_H_
|
||
|
|
||
|
/* ### what the hell? why does the APR interface have a "size" ??
|
||
|
### the implication is that, if we bust this limit, we'd need to
|
||
|
### stop, rebuild a pollset, and repopulate it. what suckage. */
|
||
|
#define MAX_CONN 16
|
||
|
|
||
|
/* Windows does not define IOV_MAX, so we need to ensure it is defined. */
|
||
|
#ifndef IOV_MAX
|
||
|
#define IOV_MAX 16
|
||
|
#endif
|
||
|
|
||
|
#define SERF_IO_CLIENT (1)
|
||
|
#define SERF_IO_CONN (2)
|
||
|
#define SERF_IO_LISTENER (3)
|
||
|
|
||
|
/* Internal logging facilities, set flag to 1 to enable console logging for
|
||
|
the selected component. */
|
||
|
#define SSL_VERBOSE 0
|
||
|
#define SSL_MSG_VERBOSE 0 /* logs decrypted requests and responses. */
|
||
|
#define SOCK_VERBOSE 0
|
||
|
#define SOCK_MSG_VERBOSE 0 /* logs bytes received from or written to a socket. */
|
||
|
#define CONN_VERBOSE 0
|
||
|
#define AUTH_VERBOSE 0
|
||
|
|
||
|
|
||
|
typedef struct serf__authn_scheme_t serf__authn_scheme_t;
|
||
|
|
||
|
typedef struct serf_io_baton_t {
|
||
|
int type;
|
||
|
union {
|
||
|
serf_incoming_t *client;
|
||
|
serf_connection_t *conn;
|
||
|
serf_listener_t *listener;
|
||
|
} u;
|
||
|
} serf_io_baton_t;
|
||
|
|
||
|
/* Holds all the information corresponding to a request/response pair. */
|
||
|
struct serf_request_t {
|
||
|
serf_connection_t *conn;
|
||
|
|
||
|
apr_pool_t *respool;
|
||
|
serf_bucket_alloc_t *allocator;
|
||
|
|
||
|
/* The bucket corresponding to the request. Will be NULL once the
|
||
|
* bucket has been emptied (for delivery into the socket).
|
||
|
*/
|
||
|
serf_bucket_t *req_bkt;
|
||
|
|
||
|
serf_request_setup_t setup;
|
||
|
void *setup_baton;
|
||
|
|
||
|
serf_response_acceptor_t acceptor;
|
||
|
void *acceptor_baton;
|
||
|
|
||
|
serf_response_handler_t handler;
|
||
|
void *handler_baton;
|
||
|
|
||
|
serf_bucket_t *resp_bkt;
|
||
|
|
||
|
int written;
|
||
|
int priority;
|
||
|
|
||
|
/* This baton is currently only used for digest authentication, which
|
||
|
needs access to the uri of the request in the response handler.
|
||
|
If serf_request_t is replaced by a serf_http_request_t in the future,
|
||
|
which knows about uri and method and such, this baton won't be needed
|
||
|
anymore. */
|
||
|
void *auth_baton;
|
||
|
|
||
|
struct serf_request_t *next;
|
||
|
};
|
||
|
|
||
|
typedef struct serf_pollset_t {
|
||
|
/* the set of connections to poll */
|
||
|
apr_pollset_t *pollset;
|
||
|
} serf_pollset_t;
|
||
|
|
||
|
typedef struct serf__authn_info_t {
|
||
|
const char *realm;
|
||
|
|
||
|
const serf__authn_scheme_t *scheme;
|
||
|
|
||
|
void *baton;
|
||
|
} serf__authn_info_t;
|
||
|
|
||
|
struct serf_context_t {
|
||
|
/* the pool used for self and for other allocations */
|
||
|
apr_pool_t *pool;
|
||
|
|
||
|
void *pollset_baton;
|
||
|
serf_socket_add_t pollset_add;
|
||
|
serf_socket_remove_t pollset_rm;
|
||
|
|
||
|
/* one of our connections has a dirty pollset state. */
|
||
|
int dirty_pollset;
|
||
|
|
||
|
/* the list of active connections */
|
||
|
apr_array_header_t *conns;
|
||
|
#define GET_CONN(ctx, i) (((serf_connection_t **)(ctx)->conns->elts)[i])
|
||
|
|
||
|
/* Proxy server address */
|
||
|
apr_sockaddr_t *proxy_address;
|
||
|
|
||
|
/* Progress callback */
|
||
|
serf_progress_t progress_func;
|
||
|
void *progress_baton;
|
||
|
apr_off_t progress_read;
|
||
|
apr_off_t progress_written;
|
||
|
|
||
|
/* authentication info for this context, shared by all connections. */
|
||
|
serf__authn_info_t authn_info;
|
||
|
serf__authn_info_t proxy_authn_info;
|
||
|
|
||
|
/* List of authn types supported by the client.*/
|
||
|
int authn_types;
|
||
|
/* Callback function used to get credentials for a realm. */
|
||
|
serf_credentials_callback_t cred_cb;
|
||
|
};
|
||
|
|
||
|
struct serf_listener_t {
|
||
|
serf_context_t *ctx;
|
||
|
serf_io_baton_t baton;
|
||
|
apr_socket_t *skt;
|
||
|
apr_pool_t *pool;
|
||
|
apr_pollfd_t desc;
|
||
|
void *accept_baton;
|
||
|
serf_accept_client_t accept_func;
|
||
|
};
|
||
|
|
||
|
struct serf_incoming_t {
|
||
|
serf_context_t *ctx;
|
||
|
serf_io_baton_t baton;
|
||
|
void *request_baton;
|
||
|
serf_incoming_request_cb_t request;
|
||
|
apr_socket_t *skt;
|
||
|
apr_pollfd_t desc;
|
||
|
};
|
||
|
|
||
|
/* States for the different stages in the lifecyle of a connection. */
|
||
|
typedef enum {
|
||
|
SERF_CONN_INIT, /* no socket created yet */
|
||
|
SERF_CONN_SETUP_SSLTUNNEL, /* ssl tunnel being setup, no requests sent */
|
||
|
SERF_CONN_CONNECTED, /* conn is ready to send requests */
|
||
|
SERF_CONN_CLOSING, /* conn is closing, no more requests,
|
||
|
start a new socket */
|
||
|
} serf__connection_state_t;
|
||
|
|
||
|
struct serf_connection_t {
|
||
|
serf_context_t *ctx;
|
||
|
|
||
|
apr_status_t status;
|
||
|
serf_io_baton_t baton;
|
||
|
|
||
|
apr_pool_t *pool;
|
||
|
serf_bucket_alloc_t *allocator;
|
||
|
|
||
|
apr_sockaddr_t *address;
|
||
|
|
||
|
apr_socket_t *skt;
|
||
|
apr_pool_t *skt_pool;
|
||
|
|
||
|
/* the last reqevents we gave to pollset_add */
|
||
|
apr_int16_t reqevents;
|
||
|
|
||
|
/* the events we've seen for this connection in our returned pollset */
|
||
|
apr_int16_t seen_in_pollset;
|
||
|
|
||
|
/* are we a dirty connection that needs its poll status updated? */
|
||
|
int dirty_conn;
|
||
|
|
||
|
/* number of completed requests we've sent */
|
||
|
unsigned int completed_requests;
|
||
|
|
||
|
/* number of completed responses we've got */
|
||
|
unsigned int completed_responses;
|
||
|
|
||
|
/* keepalive */
|
||
|
unsigned int probable_keepalive_limit;
|
||
|
|
||
|
/* Current state of the connection (whether or not it is connected). */
|
||
|
serf__connection_state_t state;
|
||
|
|
||
|
/* This connection may have responses without a request! */
|
||
|
int async_responses;
|
||
|
serf_bucket_t *current_async_response;
|
||
|
serf_response_acceptor_t async_acceptor;
|
||
|
void *async_acceptor_baton;
|
||
|
serf_response_handler_t async_handler;
|
||
|
void *async_handler_baton;
|
||
|
|
||
|
/* A bucket wrapped around our socket (for reading responses). */
|
||
|
serf_bucket_t *stream;
|
||
|
/* A reference to the aggregate bucket that provides the boundary between
|
||
|
* request level buckets and connection level buckets.
|
||
|
*/
|
||
|
serf_bucket_t *ostream_head;
|
||
|
serf_bucket_t *ostream_tail;
|
||
|
|
||
|
/* Aggregate bucket used to send the CONNECT request. */
|
||
|
serf_bucket_t *ssltunnel_ostream;
|
||
|
|
||
|
/* The list of active requests. */
|
||
|
serf_request_t *requests;
|
||
|
serf_request_t *requests_tail;
|
||
|
|
||
|
struct iovec vec[IOV_MAX];
|
||
|
int vec_len;
|
||
|
|
||
|
serf_connection_setup_t setup;
|
||
|
void *setup_baton;
|
||
|
serf_connection_closed_t closed;
|
||
|
void *closed_baton;
|
||
|
|
||
|
/* Max. number of outstanding requests. */
|
||
|
unsigned int max_outstanding_requests;
|
||
|
|
||
|
int hit_eof;
|
||
|
/* Host info. */
|
||
|
const char *host_url;
|
||
|
apr_uri_t host_info;
|
||
|
|
||
|
/* connection and authentication scheme specific information */
|
||
|
void *authn_baton;
|
||
|
void *proxy_authn_baton;
|
||
|
|
||
|
/* Time marker when connection begins. */
|
||
|
apr_time_t connect_time;
|
||
|
|
||
|
/* Calculated connection latency. Negative value if latency is unknown. */
|
||
|
apr_interval_time_t latency;
|
||
|
};
|
||
|
|
||
|
/*** Internal bucket functions ***/
|
||
|
|
||
|
/** Transform a response_bucket in-place into an aggregate bucket. Restore the
|
||
|
status line and all headers, not just the body.
|
||
|
|
||
|
This can only be used when we haven't started reading the body of the
|
||
|
response yet.
|
||
|
|
||
|
Keep internal for now, probably only useful within serf.
|
||
|
*/
|
||
|
apr_status_t serf_response_full_become_aggregate(serf_bucket_t *bucket);
|
||
|
|
||
|
/*** Authentication handler declarations ***/
|
||
|
|
||
|
typedef enum { PROXY, HOST } peer_t;
|
||
|
|
||
|
/**
|
||
|
* For each authentication scheme we need a handler function of type
|
||
|
* serf__auth_handler_func_t. This function will be called when an
|
||
|
* authentication challenge is received in a session.
|
||
|
*/
|
||
|
typedef apr_status_t
|
||
|
(*serf__auth_handler_func_t)(int code,
|
||
|
serf_request_t *request,
|
||
|
serf_bucket_t *response,
|
||
|
const char *auth_hdr,
|
||
|
const char *auth_attr,
|
||
|
void *baton,
|
||
|
apr_pool_t *pool);
|
||
|
|
||
|
/**
|
||
|
* For each authentication scheme we need an initialization function of type
|
||
|
* serf__init_context_func_t. This function will be called the first time
|
||
|
* serf tries a specific authentication scheme handler.
|
||
|
*/
|
||
|
typedef apr_status_t
|
||
|
(*serf__init_context_func_t)(int code,
|
||
|
serf_context_t *conn,
|
||
|
apr_pool_t *pool);
|
||
|
|
||
|
/**
|
||
|
* For each authentication scheme we need an initialization function of type
|
||
|
* serf__init_conn_func_t. This function will be called when a new
|
||
|
* connection is opened.
|
||
|
*/
|
||
|
typedef apr_status_t
|
||
|
(*serf__init_conn_func_t)(int code,
|
||
|
serf_connection_t *conn,
|
||
|
apr_pool_t *pool);
|
||
|
|
||
|
/**
|
||
|
* For each authentication scheme we need a setup_request function of type
|
||
|
* serf__setup_request_func_t. This function will be called when a
|
||
|
* new serf_request_t object is created and should fill in the correct
|
||
|
* authentication headers (if needed).
|
||
|
*/
|
||
|
typedef apr_status_t
|
||
|
(*serf__setup_request_func_t)(peer_t peer,
|
||
|
int code,
|
||
|
serf_connection_t *conn,
|
||
|
serf_request_t *request,
|
||
|
const char *method,
|
||
|
const char *uri,
|
||
|
serf_bucket_t *hdrs_bkt);
|
||
|
|
||
|
/**
|
||
|
* This function will be called when a response is received, so that the
|
||
|
* scheme handler can validate the Authentication related response headers
|
||
|
* (if needed).
|
||
|
*/
|
||
|
typedef apr_status_t
|
||
|
(*serf__validate_response_func_t)(peer_t peer,
|
||
|
int code,
|
||
|
serf_connection_t *conn,
|
||
|
serf_request_t *request,
|
||
|
serf_bucket_t *response,
|
||
|
apr_pool_t *pool);
|
||
|
|
||
|
/**
|
||
|
* serf__authn_scheme_t: vtable for an authn scheme provider.
|
||
|
*/
|
||
|
struct serf__authn_scheme_t {
|
||
|
/* The http status code that's handled by this authentication scheme.
|
||
|
Normal values are 401 for server authentication and 407 for proxy
|
||
|
authentication */
|
||
|
int code;
|
||
|
|
||
|
/* The name of this authentication scheme. This should be a case
|
||
|
sensitive match of the string sent in the HTTP authentication header. */
|
||
|
const char *name;
|
||
|
|
||
|
/* Internal code used for this authn type. */
|
||
|
int type;
|
||
|
|
||
|
/* The context initialization function if any; otherwise, NULL */
|
||
|
serf__init_context_func_t init_ctx_func;
|
||
|
|
||
|
/* The connection initialization function if any; otherwise, NULL */
|
||
|
serf__init_conn_func_t init_conn_func;
|
||
|
|
||
|
/* The authentication handler function */
|
||
|
serf__auth_handler_func_t handle_func;
|
||
|
|
||
|
/* Function to set up the authentication header of a request */
|
||
|
serf__setup_request_func_t setup_request_func;
|
||
|
|
||
|
/* Function to validate the authentication header of a response */
|
||
|
serf__validate_response_func_t validate_response_func;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handles a 401 or 407 response, tries the different available authentication
|
||
|
* handlers.
|
||
|
*/
|
||
|
apr_status_t serf__handle_auth_response(int *consumed_response,
|
||
|
serf_request_t *request,
|
||
|
serf_bucket_t *response,
|
||
|
void *baton,
|
||
|
apr_pool_t *pool);
|
||
|
|
||
|
/* fromt context.c */
|
||
|
void serf__context_progress_delta(void *progress_baton, apr_off_t read,
|
||
|
apr_off_t written);
|
||
|
|
||
|
/* from incoming.c */
|
||
|
apr_status_t serf__process_client(serf_incoming_t *l, apr_int16_t events);
|
||
|
apr_status_t serf__process_listener(serf_listener_t *l);
|
||
|
|
||
|
/* from outgoing.c */
|
||
|
apr_status_t serf__open_connections(serf_context_t *ctx);
|
||
|
apr_status_t serf__process_connection(serf_connection_t *conn,
|
||
|
apr_int16_t events);
|
||
|
apr_status_t serf__conn_update_pollset(serf_connection_t *conn);
|
||
|
|
||
|
/* from ssltunnel.c */
|
||
|
apr_status_t serf__ssltunnel_connect(serf_connection_t *conn);
|
||
|
|
||
|
|
||
|
/** Logging functions. Use one of the [COMP]_VERBOSE flags to enable specific
|
||
|
logging.
|
||
|
**/
|
||
|
|
||
|
/* Logs a standard event, with filename & timestamp header */
|
||
|
void serf__log(int verbose_flag, const char *filename, const char *fmt, ...);
|
||
|
|
||
|
/* Logs a standard event, but without prefix. This is useful to build up
|
||
|
log lines in parts. */
|
||
|
void serf__log_nopref(int verbose_flag, const char *fmt, ...);
|
||
|
|
||
|
/* Logs a socket event, add local and remote ip address:port */
|
||
|
void serf__log_skt(int verbose_flag, const char *filename, apr_socket_t *skt,
|
||
|
const char *fmt, ...);
|
||
|
|
||
|
#endif
|