+Serf 0.2 [2008-06-06, r1188]
+ Enable use of external event loop: serf_create_context_ex.
+ Enable adding new requests at the beginning of the request queue.
+ Handle 'Connection:close' headers.
+ Enable limiting the number of outstanding requests.
+ Add readline function to simple buckets.
+ Concatenate repeated headers using comma as separator, as per RFC 2616,
+ section 4.2. (Issue 29)
+ Add proxy server support.
+ Add progress feedback support. (Issue 11)
+ Provide new API to simplify use of proxy and progress feedback support.
+ Add callback to validate SSL server certificates. (Issue 31)
+ Add new test framework.
+ Send current version string in the test programs (Issue 21)
+ Bugfixes:
+ Fix segfault with epoll when removing a NULL socket.
+ Reset OpenSSL thread-safety callbacks when apr_terminate() called.
+ Do not remove the socket from the pollset on pool cleanup.
+ Do not issue double close on skt w/second one being close(-1) (Issue 33)
+
Serf 0.1.2 [2007-6-18, r1114]
Enable thread-safety with OpenSSL (Issue 19)
Teach serfmake to install headers into include/serf-0.
+++ /dev/null
-#
-# Makefile for Serf
-#
-srcdir = .
-
-
-SERF_MAJOR_VERSION=0
-SERF_DOTTED_VERSION=0.1.2
-
-OBJECTS = buckets/aggregate_buckets.lo buckets/request_buckets.lo context.lo \
- buckets/buckets.lo buckets/simple_buckets.lo buckets/file_buckets.lo \
- buckets/mmap_buckets.lo buckets/socket_buckets.lo \
- buckets/response_buckets.lo buckets/headers_buckets.lo \
- buckets/allocator.lo buckets/dechunk_buckets.lo \
- buckets/deflate_buckets.lo buckets/limit_buckets.lo \
- buckets/ssl_buckets.lo buckets/barrier_buckets.lo \
- buckets/chunk_buckets.lo
-
-TARGET_LIB=libserf-$(SERF_MAJOR_VERSION).la
-
-TEST_OBJECTS = test/serf_get.lo test/serf_response.lo test/serf_request.lo \
- test/serf_spider.lo
-PROGRAMS = $(TEST_OBJECTS:.lo=)
-
-TESTCASES = test/testcases/simple.response \
- test/testcases/chunked-empty.response test/testcases/chunked.response \
- test/testcases/chunked-trailers.response \
- test/testcases/deflate.response
-
-HEADERS = serf.h serf_bucket_types.h serf_bucket_util.h serf_declare.h
-
-prefix=/usr/local/serf
-exec_prefix=${prefix}
-libdir=${exec_prefix}/lib
-includedir=${prefix}/include/serf-${SERF_MAJOR_VERSION}
-
-LIBTOOL = /usr/share/apr-1.0/build/libtool --silent
-CC = i486-linux-gnu-gcc
-CFLAGS = -fPIC -pipe -Wall -g -O2 -pthread
-CPPFLAGS = -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE
-INCLUDES = -I$(srcdir) -I/usr/include/apr-1.0 -I/usr/include/apr-1.0 $(EXTRA_INCLUDES)
-MKDIR = mkdir -p
-INSTALL = /usr/bin/install -c
-
-LDFLAGS =
-LIBS = /usr/lib/libaprutil-1.la /usr/lib/libapr-1.la -luuid -lrt -lcrypt -lpthread -ldl -lz -lssl -lcrypto
-
-all: $(TARGET_LIB) $(PROGRAMS)
-
-context.lo: context.c $(HEADERS)
-buckets/aggregate_buckets.lo: buckets/aggregate_buckets.c $(HEADERS)
-buckets/request_buckets.lo: buckets/request_buckets.c $(HEADERS)
-buckets/buckets.lo: buckets/buckets.c $(HEADERS)
-buckets/simple_buckets.lo: buckets/simple_buckets.c $(HEADERS)
-buckets/file_buckets.lo: buckets/file_buckets.c $(HEADERS)
-buckets/mmap_buckets.lo: buckets/mmap_buckets.c $(HEADERS)
-buckets/socket_buckets.lo: buckets/socket_buckets.c $(HEADERS)
-buckets/response_buckets.lo: buckets/response_buckets.c $(HEADERS)
-buckets/headers_buckets.lo: buckets/headers_buckets.c $(HEADERS)
-buckets/allocator.lo: buckets/allocator.c $(HEADERS)
-buckets/dechunk_buckets.lo: buckets/dechunk_buckets.c $(HEADERS)
-buckets/deflate_buckets.lo: buckets/deflate_buckets.c $(HEADERS)
-buckets/limit_buckets.lo: buckets/limit_buckets.c $(HEADERS)
-buckets/ssl_buckets.lo: buckets/ssl_buckets.c $(HEADERS)
-buckets/barrier_buckets.lo: buckets/barrier_buckets.c $(HEADERS)
-buckets/chunk_buckets.lo: buckets/chunk_buckets.c $(HEADERS)
-
-test/serf_get.lo: test/serf_get.c $(HEADERS)
-test/serf_response.lo: test/serf_response.c $(HEADERS)
-test/serf_request.lo: test/serf_request.c $(HEADERS)
-test/serf_spider.lo: test/serf_spider.c $(HEADERS)
-
-$(TARGET_LIB): $(OBJECTS)
- $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -rpath $(libdir) -o $@ $^ $(LIBS)
-
-test/serf_get: $(TARGET_LIB) test/serf_get.lo
- $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -static -o $@ $^ $(LIBS)
-
-test/serf_response: $(TARGET_LIB) test/serf_response.lo
- $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -static -o $@ $^ $(LIBS)
-
-test/serf_request: $(TARGET_LIB) test/serf_request.lo
- $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -static -o $@ $^ $(LIBS)
-
-test/serf_spider: $(TARGET_LIB) test/serf_spider.lo
- $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -static -o $@ $^ $(LIBS)
-
-
-check: test/serf_response
- @for i in $(TESTCASES); \
- do echo "== Testing $$i =="; \
- ./test/serf_response $$i; \
- done;
-
-install: $(TARGET_LIB)
- $(MKDIR) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir)
- $(LIBTOOL) --mode=install $(INSTALL) -m 644 $(TARGET_LIB) $(DESTDIR)$(libdir)
- for i in $(srcdir)/*.h; do \
- $(INSTALL) -m 644 $$i $(DESTDIR)$(includedir); \
- done
-
-clean:
- rm -f $(TARGET_LIB) $(OBJECTS) $(OBJECTS:.lo=.o) $(PROGRAMS) $(TEST_OBJECTS) $(TEST_OBJECTS:.lo=.o)
- for subdir in . buckets test; do \
- (cd $$subdir && rm -rf .libs) ; \
- done
-
-distclean: clean
- rm -f Makefile config.log config.status
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o
-
-mkdir-vpath:
- @if [ ! -d buckets ]; then \
- $(MKDIR) buckets; \
- fi;
- @if [ ! -d test ]; then \
- $(MKDIR) test; \
- fi;
-
-.c.lo:
- $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $< && touch $@
TEST_OBJECTS = test/serf_get.lo test/serf_response.lo test/serf_request.lo \
test/serf_spider.lo
-PROGRAMS = $(TEST_OBJECTS:.lo=)
+
+TEST_SUITE_OBJECTS = test/CuTest.lo test/test_all.lo test/test_util.lo \
+ test/test_buckets.lo test/test_context.lo \
+ test/test_ssl.lo
+
+PROGRAMS = $(TEST_OBJECTS:.lo=) test/test_all
TESTCASES = test/testcases/simple.response \
test/testcases/chunked-empty.response test/testcases/chunked.response \
test/serf_request.lo: test/serf_request.c $(HEADERS)
test/serf_spider.lo: test/serf_spider.c $(HEADERS)
+test/CuTest.lo: test/CuTest.c $(HEADERS)
+test/test_all.lo: test/test_all.c $(HEADERS)
+test/test_util.lo: test/test_util.c $(HEADERS)
+test/test_buckets.lo: test/test_buckets.c $(HEADERS)
+test/test_context.lo: test/test_context.c $(HEADERS)
+test/test_ssl.lo: test/test_ssl.c $(HEADERS)
+
$(TARGET_LIB): $(OBJECTS)
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -rpath $(libdir) -o $@ $^ $(LIBS)
test/serf_spider: $(TARGET_LIB) test/serf_spider.lo
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -static -o $@ $^ $(LIBS)
+test/test_all: $(TARGET_LIB) $(TEST_SUITE_OBJECTS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -static -o $@ $^ $(LIBS)
-check: test/serf_response
+check: test/serf_response test/test_all
@for i in $(TESTCASES); \
do echo "== Testing $$i =="; \
./test/serf_response $$i; \
done;
+ @echo "== Running test_all ==";
+ @./test/test_all
install: $(TARGET_LIB)
$(MKDIR) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir)
done
clean:
- rm -f $(TARGET_LIB) $(OBJECTS) $(OBJECTS:.lo=.o) $(PROGRAMS) $(TEST_OBJECTS) $(TEST_OBJECTS:.lo=.o)
+ rm -f $(TARGET_LIB) $(OBJECTS) $(OBJECTS:.lo=.o) $(PROGRAMS) $(TEST_OBJECTS) $(TEST_OBJECTS:.lo=.o) $(TEST_SUITE_OBJECTS) $(TEST_SUITE_OBJECTS:.lo=.o)
for subdir in . buckets test; do \
(cd $$subdir && rm -rf .libs) ; \
done
new_list->bucket = append_bucket;
new_list->next = NULL;
- /* If we use APR_RING, this is trivial. So, wait.
+ /* If we use APR_RING, this is trivial. So, wait.
new_list->next = ctx->list;
ctx->list = new_list;
*/
* limitations under the License.
*/
-#include <stdlib.h> /* for abort() */
-
#include <apr_pools.h>
#include "serf.h"
* limitations under the License.
*/
-#include <stdlib.h>
-
#include <apr_strings.h>
#include "serf.h"
* limitations under the License.
*/
-#include <stdlib.h>
-
#include <apr_strings.h>
#include <zlib.h>
/* ### need to implement */
#define serf_deflate_readline NULL
-#define serf_deflate_read_iovec NULL
-#define serf_deflate_read_for_sendfile NULL
#define serf_deflate_peek NULL
SERF_DECLARE_DATA const serf_bucket_type_t serf_bucket_type_deflate = {
"DEFLATE",
serf_deflate_read,
serf_deflate_readline,
- serf_deflate_read_iovec,
- serf_deflate_read_for_sendfile,
+ serf_default_read_iovec,
+ serf_default_read_for_sendfile,
serf_default_read_bucket,
serf_deflate_peek,
serf_deflate_destroy_and_data,
const char *value, apr_size_t value_size, int value_copy)
{
headers_context_t *ctx = bkt->data;
- header_list_t *hdr = serf_bucket_mem_alloc(bkt->allocator, sizeof(*hdr));
+ header_list_t *found = ctx->list;
+ header_list_t *hdr;
- /* ### should check if the header exists before adding. overwrite. */
+ /* Check to see if this header is already present. */
+ while (found) {
+ if (strncasecmp(found->header, header, header_size) == 0)
+ break;
+ found = found->next;
+ }
+
+ if (found) {
+
+ /* The header is already present. RFC 2616, section 4.2
+ indicates that we should append the new value, separated by
+ a comma. Reasoning: for headers whose values are known to
+ be comma-separated, that is clearly the correct behavior;
+ for others, the correct behavior is undefined anyway. */
+
+ /* The "+1" is for the comma; serf_bstrmemdup() will also add
+ one slot for the terminating '\0'. */
+ apr_size_t new_size = found->value_size + value_size + 1;
+ char *new_val = serf_bucket_mem_alloc(bkt->allocator, new_size);
+ memcpy(new_val, found->value, found->value_size);
+ new_val[found->value_size] = ',';
+ memcpy(new_val + found->value_size + 1, value, value_size);
+ new_val[new_size] = '\0';
+ found->value = new_val;
+ found->value_size = new_size;
+ found->alloc_flags |= ALLOC_VALUE;
+ return;
+ }
+
+ /* Else the header is not already present. Add it to the bucket. */
#if 0
/* ### include this? */
}
#endif
+ hdr = serf_bucket_mem_alloc(bkt->allocator, sizeof(*hdr));
hdr->header_size = header_size;
hdr->value_size = value_size;
hdr->alloc_flags = 0;
SERF_DECLARE(void) serf_bucket_headers_do(
serf_bucket_t *headers_bucket,
- serf_bucket_headers_do_callback_fn_t func,
+ serf_bucket_headers_do_callback_fn_t func,
void *baton)
{
headers_context_t *ctx = headers_bucket->data;
if (requested >= avail) {
/* return everything from this chunk */
*len = avail;
-
+
/* we consumed this chunk. advance the state. */
return consume_chunk(ctx);
}
* limitations under the License.
*/
-#include <stdlib.h>
-
#include <apr_pools.h>
#include <apr_strings.h>
return ((request_context_t *)bucket->data)->headers;
}
+SERF_DECLARE(void) serf_bucket_request_set_root(
+ serf_bucket_t *bucket,
+ const char *root_url)
+{
+ request_context_t *ctx = (request_context_t *)bucket->data;
+
+ /* If uri is already absolute, don't change it. */
+ if (ctx->uri[0] != '/')
+ return;
+
+ /* If uri is '/' replace it with root_url. */
+ if (ctx->uri[1] == '\0')
+ ctx->uri = root_url;
+ else
+ ctx->uri =
+ apr_pstrcat(serf_bucket_allocator_get_pool(bucket->allocator),
+ root_url,
+ ctx->uri,
+ NULL);
+}
+
static void serialize_data(serf_bucket_t *bucket)
{
request_context_t *ctx = bucket->data;
* limitations under the License.
*/
-#include <stdlib.h>
-
#include <apr_lib.h>
#include <apr_strings.h>
#include <apr_date.h>
}
/* ### need to implement */
-#define serf_response_read_iovec NULL
-#define serf_response_read_for_sendfile NULL
#define serf_response_peek NULL
SERF_DECLARE_DATA const serf_bucket_type_t serf_bucket_type_response = {
"RESPONSE",
serf_response_read,
serf_response_readline,
- serf_response_read_iovec,
- serf_response_read_for_sendfile,
+ serf_default_read_iovec,
+ serf_default_read_for_sendfile,
serf_default_read_bucket,
serf_response_peek,
serf_response_destroy_and_data,
int acceptable, int *found,
const char **data, apr_size_t *len)
{
- /* ### need our utility function... */
- return APR_ENOTIMPL;
+ simple_context_t *ctx = bucket->data;
+
+ /* Returned data will be from current position. */
+ *data = ctx->current;
+ serf_util_readline(&ctx->current, &ctx->remaining, acceptable, found);
+
+ /* See how much ctx->current moved forward. */
+ *len = ctx->current - *data;
+
+ return ctx->remaining ? APR_SUCCESS : APR_EOF;
}
static apr_status_t serf_simple_peek(serf_bucket_t *bucket,
serf_databuf_t databuf;
+ /* Progress callback */
+ serf_progress_t progress_func;
+ void *progress_baton;
} socket_context_t;
char *buf, apr_size_t *len)
{
socket_context_t *ctx = baton;
+ apr_status_t status;
*len = bufsize;
- return apr_socket_recv(ctx->skt, buf, len);
+ status = apr_socket_recv(ctx->skt, buf, len);
+
+ if (ctx->progress_func)
+ ctx->progress_func(ctx->progress_baton, *len, 0);
+
+ return status;
}
SERF_DECLARE(serf_bucket_t *) serf_bucket_socket_create(
ctx->databuf.read = socket_reader;
ctx->databuf.read_baton = ctx;
+ ctx->progress_func = ctx->progress_baton = NULL;
return serf_bucket_create(&serf_bucket_type_socket, allocator, ctx);
}
+SERF_DECLARE(void) serf_bucket_socket_set_read_progress_cb(
+ serf_bucket_t *bucket,
+ const serf_progress_t progress_func,
+ void *progress_baton)
+{
+ socket_context_t *ctx = bucket->data;
+
+ ctx->progress_func = progress_func;
+ ctx->progress_baton = progress_baton;
+}
+
static apr_status_t serf_socket_read(serf_bucket_t *bucket,
apr_size_t requested,
const char **data, apr_size_t *len)
apr_pool_t *cert_pw_cache_pool;
const char *cert_pw_success;
+ /* Server cert callbacks */
+ serf_ssl_need_server_cert_t server_cert_callback;
+ void *server_cert_userdata;
+
const char *cert_path;
X509 *cached_cert;
EVP_PKEY *cached_cert_pw;
+
+ apr_status_t pending_err;
};
typedef struct {
serf_bucket_t **our_stream;
} ssl_context_t;
+struct serf_ssl_certificate_t {
+ X509 *ssl_cert;
+};
/* Returns the amount read. */
static int bio_bucket_read(BIO *bio, char *in, int inlen)
static int bio_file_read(BIO *bio, char *in, int inlen)
{
apr_file_t *file = bio->ptr;
- const char *data;
apr_status_t status;
apr_size_t len;
#endif
};
+static int
+validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
+{
+ SSL *ssl;
+ serf_ssl_context_t *ctx;
+ X509 *server_cert;
+ int err, depth;
+ int failures = 0;
+
+ ssl = X509_STORE_CTX_get_ex_data(store_ctx,
+ SSL_get_ex_data_X509_STORE_CTX_idx());
+ ctx = SSL_get_app_data(ssl);
+
+ server_cert = X509_STORE_CTX_get_current_cert(store_ctx);
+ depth = X509_STORE_CTX_get_error_depth(store_ctx);
+
+ /* If the certification was found invalid, get the error and convert it to
+ something our caller will understand. */
+ if (! cert_valid) {
+ err = X509_STORE_CTX_get_error(store_ctx);
+
+ switch(err) {
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ failures |= SERF_SSL_CERT_NOTYETVALID;
+ break;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ failures |= SERF_SSL_CERT_EXPIRED;
+ break;
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ failures |= SERF_SSL_CERT_SELF_SIGNED;
+ break;
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ failures |= SERF_SSL_CERT_UNKNOWNCA;
+ break;
+ default:
+ failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
+ break;
+ }
+ }
+
+ /* Check certificate expiry dates. */
+ if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
+ failures |= SERF_SSL_CERT_NOTYETVALID;
+ }
+ else if (X509_cmp_current_time(X509_get_notAfter(server_cert)) <= 0) {
+ failures |= SERF_SSL_CERT_EXPIRED;
+ }
+
+ if (ctx->server_cert_callback &&
+ (depth == 0 || failures)) {
+ apr_status_t status;
+ serf_ssl_certificate_t *cert;
+ apr_pool_t *subpool;
+
+ apr_pool_create(&subpool, ctx->pool);
+
+ cert = apr_palloc(subpool, sizeof(serf_ssl_certificate_t));
+ cert->ssl_cert = server_cert;
+
+ /* Callback for further verification. */
+ status = ctx->server_cert_callback(ctx->server_cert_userdata,
+ failures, cert);
+ if (status == APR_SUCCESS)
+ cert_valid = 1;
+ else
+ /* Pass the error back to the caller through the context-run. */
+ ctx->pending_err = status;
+ apr_pool_destroy(subpool);
+ }
+
+ return cert_valid;
+}
+
/* This function reads an encrypted stream and returns the decrypted stream. */
static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
char *buf, apr_size_t *len)
*len = 0;
status = APR_EAGAIN;
break;
+ case SSL_ERROR_SSL:
+ *len = 0;
+ status = ctx->pending_err;
+ ctx->pending_err = 0;
+ break;
default:
*len = 0;
status = APR_EGENERAL;
/* FIXME: This is lame and not portable. -aaron */
return (unsigned long) apr_os_thread_current();
}
+
+static apr_status_t cleanup_ssl(void *data)
+{
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_id_callback(NULL);
+ CRYPTO_set_dynlock_create_callback(NULL);
+ CRYPTO_set_dynlock_lock_callback(NULL);
+ CRYPTO_set_dynlock_destroy_callback(NULL);
+
+ return APR_SUCCESS;
+}
+
#endif
static int have_init_ssl = 0;
CRYPTO_set_dynlock_create_callback(ssl_dyn_create);
CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock);
CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy);
+
+ apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl);
#endif
have_init_ssl = 1;
}
}
+SERF_DECLARE(void)
+serf_ssl_server_cert_callback_set(serf_ssl_context_t *context,
+ serf_ssl_need_server_cert_t callback,
+ void *data)
+{
+ context->server_cert_callback = callback;
+ context->server_cert_userdata = data;
+}
+
static serf_ssl_context_t *ssl_init_context(void)
{
serf_ssl_context_t *ssl_ctx;
ssl_ctx->cached_cert = 0;
ssl_ctx->cached_cert_pw = 0;
+ SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER,
+ validate_server_certificate);
SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL);
ssl_ctx->ssl = SSL_new(ssl_ctx->ctx);
return serf_bucket_create(type, allocator, ctx);
}
+SERF_DECLARE(apr_status_t)
+serf_ssl_use_default_certificates(serf_ssl_context_t *ssl_ctx)
+{
+ X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
+
+ int result = X509_STORE_set_default_paths(store);
+
+ return result ? APR_SUCCESS : APR_EGENERAL;
+}
+
+SERF_DECLARE(apr_status_t)
+serf_ssl_load_cert_file(serf_ssl_certificate_t **cert, const char *file_path,
+ apr_pool_t *pool)
+{
+ FILE *fp = fopen(file_path, "r");
+
+ if (fp) {
+ X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
+ fclose(fp);
+
+ if (ssl_cert) {
+ *cert = apr_palloc(pool, sizeof(serf_ssl_certificate_t));
+ (*cert)->ssl_cert = ssl_cert;
+
+ return APR_SUCCESS;
+ }
+ }
+
+ return APR_EGENERAL;
+}
+
+SERF_DECLARE(apr_status_t)
+serf_ssl_trust_cert(serf_ssl_context_t *ssl_ctx, serf_ssl_certificate_t *cert)
+{
+ X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
+
+ int result = X509_STORE_add_cert(store, cert->ssl_cert);
+
+ return result ? APR_SUCCESS : APR_EGENERAL;
+}
+
SERF_DECLARE(serf_bucket_t *) serf_bucket_ssl_decrypt_create(
serf_bucket_t *stream,
serf_ssl_context_t *ssl_ctx,
return ctx->ssl_ctx;
}
+/* Functions to read a serf_ssl_certificate structure. */
+
+/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
+static apr_hash_t *
+convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
+{
+ char buf[1024];
+ int ret;
+
+ apr_hash_t *tgt = apr_hash_make(pool);
+
+ ret = X509_NAME_get_text_by_NID(org,
+ NID_commonName,
+ buf, 1024);
+ if (ret != -1)
+ apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+ ret = X509_NAME_get_text_by_NID(org,
+ NID_pkcs9_emailAddress,
+ buf, 1024);
+ if (ret != -1)
+ apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+ ret = X509_NAME_get_text_by_NID(org,
+ NID_organizationalUnitName,
+ buf, 1024);
+ if (ret != -1)
+ apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+ ret = X509_NAME_get_text_by_NID(org,
+ NID_organizationName,
+ buf, 1024);
+ if (ret != -1)
+ apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+ ret = X509_NAME_get_text_by_NID(org,
+ NID_localityName,
+ buf, 1024);
+ if (ret != -1)
+ apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+ ret = X509_NAME_get_text_by_NID(org,
+ NID_stateOrProvinceName,
+ buf, 1024);
+ if (ret != -1)
+ apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+ ret = X509_NAME_get_text_by_NID(org,
+ NID_countryName,
+ buf, 1024);
+ if (ret != -1)
+ apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+
+ return tgt;
+}
+
+SERF_DECLARE(apr_hash_t *)
+serf_ssl_cert_issuer(const serf_ssl_certificate_t *cert, apr_pool_t *pool)
+{
+
+ X509_NAME *issuer = X509_get_issuer_name(cert->ssl_cert);
+ if (!issuer)
+ return NULL;
+
+ return convert_X509_NAME_to_table(issuer, pool);
+}
+
+SERF_DECLARE(apr_hash_t *)
+serf_ssl_cert_subject(const serf_ssl_certificate_t *cert, apr_pool_t *pool)
+{
+
+ X509_NAME *subject = X509_get_subject_name(cert->ssl_cert);
+ if (!subject)
+ return NULL;
+
+ return convert_X509_NAME_to_table(subject, pool);
+}
+
+SERF_DECLARE(apr_hash_t *)
+serf_ssl_cert_certificate(const serf_ssl_certificate_t *cert, apr_pool_t *pool)
+{
+ apr_hash_t *tgt = apr_hash_make(pool);
+ unsigned int md_size, i;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ BIO *bio;
+
+ /* sha1 fingerprint */
+ if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
+ const char hex[] = "0123456789ABCDEF";
+ char fingerprint[EVP_MAX_MD_SIZE * 3];
+
+ for (i=0; i<md_size; i++) {
+ fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4];
+ fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)];
+ fingerprint[(3*i)+2] = ':';
+ }
+ if (md_size > 0)
+ fingerprint[(3*(md_size-1))+2] = '\0';
+ else
+ fingerprint[0] = '\0';
+
+ apr_hash_set(tgt, "sha1", APR_HASH_KEY_STRING,
+ apr_pstrdup(pool, fingerprint));
+ }
+
+ /* set expiry dates */
+ bio = BIO_new(BIO_s_mem());
+ if (bio) {
+ ASN1_TIME *notBefore, *notAfter;
+ char buf[256];
+
+ memset (buf, 0, sizeof (buf));
+ notBefore = X509_get_notBefore(cert->ssl_cert);
+ if (ASN1_TIME_print(bio, notBefore)) {
+ BIO_read(bio, buf, 255);
+ apr_hash_set(tgt, "notBefore", APR_HASH_KEY_STRING,
+ apr_pstrdup(pool, buf));
+ }
+ memset (buf, 0, sizeof (buf));
+ notAfter = X509_get_notAfter(cert->ssl_cert);
+ if (ASN1_TIME_print(bio, notAfter)) {
+ BIO_read(bio, buf, 255);
+ apr_hash_set(tgt, "notAfter", APR_HASH_KEY_STRING,
+ apr_pstrdup(pool, buf));
+ }
+ }
+ BIO_free(bio);
+
+ return tgt;
+}
+
static void serf_ssl_destroy_and_data(serf_bucket_t *bucket)
{
ssl_context_t *ctx = bucket->data;
# autoconf doesn't add --silent to ac_configure_args; explicitly pass it
test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent"
- dnl The eval makes quoting arguments work - specifically $2 where the
- dnl quoting mechanisms used is "" rather than [].
+ dnl The eval makes quoting arguments work - specifically the second argument
+ dnl where the quoting mechanisms used is "" rather than [].
dnl
dnl We need to execute another shell because some autoconf/shell combinations
dnl will choke after doing repeated APR_SUBDIR_CONFIG()s. (Namely Solaris
AC_SUBST(MKDEP)
])
+
+dnl
+dnl APR_CHECK_TYPES_COMPATIBLE(TYPE-1, TYPE-2, [ACTION-IF-TRUE])
+dnl
+dnl Try to determine whether two types are the same. Only works
+dnl for gcc and icc.
+dnl
+AC_DEFUN([APR_CHECK_TYPES_COMPATIBLE], [
+define([apr_cvname], apr_cv_typematch_[]translit([$1], [ ], [_])_[]translit([$2], [ ], [_]))
+AC_CACHE_CHECK([whether $1 and $2 are the same], apr_cvname, [
+AC_TRY_COMPILE(AC_INCLUDES_DEFAULT, [
+ int foo[0 - !__builtin_types_compatible_p($1, $2)];
+], [apr_cvname=yes
+$3], [apr_cvname=no])])
+])
dnl -------------------------------------------------------- -*- autoconf -*-
-dnl Copyright 2002-2005 The Apache Software Foundation or its licensors, as
-dnl applicable.
-dnl
-dnl Licensed under the Apache License, Version 2.0 (the "License");
-dnl you may not use this file except in compliance with the License.
-dnl You may obtain a copy of the License at
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements. See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License. You may obtain a copy of the License at
dnl
dnl http://www.apache.org/licenses/LICENSE-2.0
dnl
+++ /dev/null
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by configure, which was
-generated by GNU Autoconf 2.60. Invocation command line was
-
- $ ./configure --enable-shared --with-apr=/usr/bin --with-apr-util=/usr/bin
-
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = oregano
-uname -m = i686
-uname -r = 2.4.18-bf2.4-xfs
-uname -s = Linux
-uname -v = #1 Son Jul 14 09:40:39 CEST 2002
-
-/usr/bin/uname -p = unknown
-/bin/uname -X = unknown
-
-/bin/arch = i686
-/usr/bin/arch -k = unknown
-/usr/convex/getsysinfo = unknown
-/usr/bin/hostinfo = unknown
-/bin/machine = unknown
-/usr/bin/oslevel = unknown
-/bin/universe = unknown
-
-PATH: /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin
-PATH: /usr/local/ant/bin
-PATH: /usr/local/jdk6/bin
-PATH: /usr/local/jdk6/jre/bin
-PATH: /usr/local/mysql/bin
-PATH: /usr/local/mysql/bin
-PATH: /usr/local/samba/bin
-PATH: /usr/local/bin
-PATH: /usr/bin
-PATH: /bin
-PATH: /usr/bin/X11
-PATH: /usr/games
-PATH: /usr/local/ant/bin
-PATH: /usr/local/ant/bin
-PATH: /usr/local/ant/bin
-PATH: /usr/local/jdk6/bin
-PATH: /home/konno/work/bin
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-configure:1895: checking for chosen layout
-configure:1897: result: Serf
-configure:2091: checking for working mkdir -p
-configure:2107: result: yes
-configure:2125: checking build system type
-configure:2143: result: i686-pc-linux-gnu
-configure:2165: checking host system type
-configure:2180: result: i686-pc-linux-gnu
-configure:2202: checking target system type
-configure:2217: result: i686-pc-linux-gnu
-configure:2275: checking for APR
-configure:2360: result: yes
-configure:2637: checking for APR-util
-configure:2722: result: yes
-configure:2972: checking for gcc
-configure:2999: result: i486-linux-gnu-gcc
-configure:3237: checking for C compiler version
-configure:3244: i486-linux-gnu-gcc --version >&5
-i486-linux-gnu-gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-Copyright (C) 2006 Free Software Foundation, Inc.
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-configure:3247: $? = 0
-configure:3254: i486-linux-gnu-gcc -v >&5
-Using built-in specs.
-Target: i486-linux-gnu
-Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu
-Thread model: posix
-gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
-configure:3257: $? = 0
-configure:3264: i486-linux-gnu-gcc -V >&5
-i486-linux-gnu-gcc: '-V' option must have argument
-configure:3267: $? = 1
-configure:3290: checking for C compiler default output file name
-configure:3317: i486-linux-gnu-gcc -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:3320: $? = 0
-configure:3366: result: a.out
-configure:3371: checking whether the C compiler works
-configure:3381: ./a.out
-configure:3384: $? = 0
-configure:3401: result: yes
-configure:3408: checking whether we are cross compiling
-configure:3410: result: no
-configure:3413: checking for suffix of executables
-configure:3420: i486-linux-gnu-gcc -o conftest -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:3423: $? = 0
-configure:3447: result:
-configure:3453: checking for suffix of object files
-configure:3479: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:3482: $? = 0
-configure:3505: result: o
-configure:3509: checking whether we are using the GNU C compiler
-configure:3538: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:3544: $? = 0
-configure:3551: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:3554: $? = 0
-configure:3561: test -s conftest.o
-configure:3564: $? = 0
-configure:3578: result: yes
-configure:3583: checking whether i486-linux-gnu-gcc accepts -g
-configure:3613: i486-linux-gnu-gcc -c -g -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:3619: $? = 0
-configure:3626: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:3629: $? = 0
-configure:3636: test -s conftest.o
-configure:3639: $? = 0
-configure:3769: result: yes
-configure:3786: checking for i486-linux-gnu-gcc option to accept ISO C89
-configure:3860: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:3866: $? = 0
-configure:3873: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:3876: $? = 0
-configure:3883: test -s conftest.o
-configure:3886: $? = 0
-configure:3906: result: none needed
-configure:3929: checking how to run the C preprocessor
-configure:4059: result: i486-linux-gnu-gcc -E
-configure:4088: i486-linux-gnu-gcc -E -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c
-configure:4094: $? = 0
-configure:4132: i486-linux-gnu-gcc -E -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c
-conftest.c:8:28: error: ac_nonexistent.h: No such file or directory
-configure:4138: $? = 1
-configure: failed program was:
-| /* confdefs.h. */
-| #define PACKAGE_NAME ""
-| #define PACKAGE_TARNAME ""
-| #define PACKAGE_VERSION ""
-| #define PACKAGE_STRING ""
-| #define PACKAGE_BUGREPORT ""
-| /* end confdefs.h. */
-| #include <ac_nonexistent.h>
-configure:4195: checking for a BSD-compatible install
-configure:4251: result: /usr/bin/install -c
-configure:4372: checking for grep that handles long lines and -e
-configure:4446: result: /bin/grep
-configure:4451: checking for egrep
-configure:4529: result: /bin/grep -E
-configure:4534: checking for ANSI C header files
-configure:4564: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4570: $? = 0
-configure:4577: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4580: $? = 0
-configure:4587: test -s conftest.o
-configure:4590: $? = 0
-configure:4686: i486-linux-gnu-gcc -o conftest -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4689: $? = 0
-configure:4695: ./conftest
-configure:4698: $? = 0
-configure:4715: result: yes
-configure:4739: checking for sys/types.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for sys/stat.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for stdlib.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for string.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for memory.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for strings.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for inttypes.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for stdint.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4739: checking for unistd.h
-configure:4760: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4766: $? = 0
-configure:4773: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4776: $? = 0
-configure:4783: test -s conftest.o
-configure:4786: $? = 0
-configure:4799: result: yes
-configure:4821: checking openssl/opensslv.h usability
-configure:4838: i486-linux-gnu-gcc -c -fPIC -pipe -Wall -g -O2 -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c >&5
-configure:4844: $? = 0
-configure:4851: test -z "$ac_c_werror_flag" || test ! -s conftest.err
-configure:4854: $? = 0
-configure:4861: test -s conftest.o
-configure:4864: $? = 0
-configure:4875: result: yes
-configure:4879: checking openssl/opensslv.h presence
-configure:4894: i486-linux-gnu-gcc -E -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE conftest.c
-configure:4900: $? = 0
-configure:4921: result: yes
-configure:4949: checking for openssl/opensslv.h
-configure:4956: result: yes
-configure:5129: creating ./config.status
-
-## ---------------------- ##
-## Running config.status. ##
-## ---------------------- ##
-
-This file was extended by config.status, which was
-generated by GNU Autoconf 2.60. Invocation command line was
-
- CONFIG_FILES =
- CONFIG_HEADERS =
- CONFIG_LINKS =
- CONFIG_COMMANDS =
- $ ./config.status
-
-on oregano
-
-config.status:598: creating Makefile
-config.status:783: executing mkdir-vpath commands
-
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-
-ac_cv_build=i686-pc-linux-gnu
-ac_cv_c_compiler_gnu=yes
-ac_cv_env_CC_set=
-ac_cv_env_CC_value=
-ac_cv_env_CFLAGS_set=set
-ac_cv_env_CFLAGS_value=-fPIC
-ac_cv_env_CPPFLAGS_set=
-ac_cv_env_CPPFLAGS_value=
-ac_cv_env_CPP_set=
-ac_cv_env_CPP_value=
-ac_cv_env_LDFLAGS_set=
-ac_cv_env_LDFLAGS_value=
-ac_cv_env_build_alias_set=
-ac_cv_env_build_alias_value=
-ac_cv_env_host_alias_set=
-ac_cv_env_host_alias_value=
-ac_cv_env_target_alias_set=
-ac_cv_env_target_alias_value=
-ac_cv_header_inttypes_h=yes
-ac_cv_header_memory_h=yes
-ac_cv_header_openssl_opensslv_h=yes
-ac_cv_header_stdc=yes
-ac_cv_header_stdint_h=yes
-ac_cv_header_stdlib_h=yes
-ac_cv_header_string_h=yes
-ac_cv_header_strings_h=yes
-ac_cv_header_sys_stat_h=yes
-ac_cv_header_sys_types_h=yes
-ac_cv_header_unistd_h=yes
-ac_cv_host=i686-pc-linux-gnu
-ac_cv_mkdir_p=yes
-ac_cv_objext=o
-ac_cv_path_EGREP='/bin/grep -E'
-ac_cv_path_GREP=/bin/grep
-ac_cv_path_install='/usr/bin/install -c'
-ac_cv_prog_CPP='i486-linux-gnu-gcc -E'
-ac_cv_prog_ac_ct_CC=i486-linux-gnu-gcc
-ac_cv_prog_cc_c89=
-ac_cv_prog_cc_g=yes
-ac_cv_target=i686-pc-linux-gnu
-
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-
-APR_BINDIR='/usr/bin'
-APR_CONFIG='/usr/bin/apr-config'
-APR_INCLUDEDIR='/usr/include/apr-1.0'
-APR_LIBTOOL='/usr/share/apr-1.0/build/libtool'
-APR_VERSION='1.2.7'
-APU_BINDIR='/usr/bin'
-APU_CONFIG='/usr/bin/apu-1-config'
-APU_INCLUDEDIR='/usr/include/apr-1.0'
-APU_VERSION='1.2.7'
-CC='i486-linux-gnu-gcc'
-CFLAGS='-fPIC -pipe -Wall -g -O2 -pthread'
-CPP='i486-linux-gnu-gcc -E'
-CPPFLAGS=' -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE'
-DEFS='-DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1'
-ECHO_C=''
-ECHO_N='-n'
-ECHO_T=''
-EGREP='/bin/grep -E'
-EXEEXT=''
-GREP='/bin/grep'
-INSTALL_DATA='${INSTALL} -m 644'
-INSTALL_PROGRAM='${INSTALL}'
-INSTALL_SCRIPT='${INSTALL}'
-LDFLAGS=' '
-LIBOBJS=''
-LIBS=''
-LTLIBOBJS=''
-OBJEXT='o'
-PACKAGE_BUGREPORT=''
-PACKAGE_NAME=''
-PACKAGE_STRING=''
-PACKAGE_TARNAME=''
-PACKAGE_VERSION=''
-PATH_SEPARATOR=':'
-SERF_BUILD_SRCLIB_DIRS=''
-SERF_CLEAN_SRCLIB_DIRS=''
-SERF_DOTTED_VERSION='0.1.2'
-SERF_LIBS=' /usr/lib/libaprutil-1.la /usr/lib/libapr-1.la -luuid -lrt -lcrypt -lpthread -ldl'
-SERF_MAJOR_VERSION='0'
-SHELL='/bin/sh'
-ac_ct_CC='i486-linux-gnu-gcc'
-bindir='${exec_prefix}/bin'
-build='i686-pc-linux-gnu'
-build_alias=''
-build_cpu='i686'
-build_os='linux-gnu'
-build_vendor='pc'
-datadir='${prefix}'
-datarootdir='${prefix}/share'
-docdir='${datarootdir}/doc/${PACKAGE}'
-dvidir='${docdir}'
-exec_prefix='${prefix}'
-host='i686-pc-linux-gnu'
-host_alias=''
-host_cpu='i686'
-host_os='linux-gnu'
-host_vendor='pc'
-htmldir='${docdir}'
-includedir='${prefix}/include/serf-${SERF_MAJOR_VERSION}'
-infodir='${datarootdir}/info'
-libdir='${exec_prefix}/lib'
-libexecdir='${exec_prefix}/modules'
-localedir='${datarootdir}/locale'
-localstatedir='${prefix}'
-mandir='${prefix}/man'
-mkdir_p='mkdir -p'
-oldincludedir='/usr/include'
-pdfdir='${docdir}'
-prefix='/usr/local/serf'
-program_transform_name='s,x,x,'
-psdir='${docdir}'
-sbindir='${exec_prefix}/bin'
-sharedstatedir='${prefix}/com'
-sysconfdir='${prefix}/conf'
-target='i686-pc-linux-gnu'
-target_alias=''
-target_cpu='i686'
-target_os='linux-gnu'
-target_vendor='pc'
-
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-
-#define PACKAGE_NAME ""
-#define PACKAGE_TARNAME ""
-#define PACKAGE_VERSION ""
-#define PACKAGE_STRING ""
-#define PACKAGE_BUGREPORT ""
-#define STDC_HEADERS 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-#define HAVE_MEMORY_H 1
-#define HAVE_STRINGS_H 1
-#define HAVE_INTTYPES_H 1
-#define HAVE_STDINT_H 1
-#define HAVE_UNISTD_H 1
-
-configure: exit 0
+++ /dev/null
-#! /bin/sh
-#
-# Created by configure
-
-CFLAGS="-fPIC"; export CFLAGS
-"./configure" \
-"--enable-shared" \
-"--with-apr=/usr/bin" \
-"--with-apr-util=/usr/bin" \
-"CFLAGS=-fPIC" \
-"$@"
+++ /dev/null
-#! /bin/sh
-# Generated by configure.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=${CONFIG_SHELL-/bin/sh}
-## --------------------- ##
-## M4sh Initialization. ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
- emulate sh
- NULLCMD=:
- # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
- # is contrary to our usage. Disable this feature.
- alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
-fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
-
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
- echo "#! /bin/sh" >conf$$.sh
- echo "exit 0" >>conf$$.sh
- chmod +x conf$$.sh
- if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
- PATH_SEPARATOR=';'
- else
- PATH_SEPARATOR=:
- fi
- rm -f conf$$.sh
-fi
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-as_nl='
-'
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- { (exit 1); exit 1; }
-fi
-
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
- fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# CDPATH.
-$as_unset CDPATH
-
-
-
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
-
- # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
- # uniformly replaced by the line number. The first 'sed' inserts a
- # line-number line after each line using $LINENO; the second 'sed'
- # does the real work. The second script uses 'N' to pair each
- # line-number line with the line containing $LINENO, and appends
- # trailing '-' during substitution so that $LINENO is not a special
- # case at line end.
- # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
- # scripts with optimization help from Paolo Bonzini. Blame Lee
- # E. McMahon (1931-1989) for sed's syntax. :-)
- sed -n '
- p
- /[$]LINENO/=
- ' <$as_myself |
- sed '
- s/[$]LINENO.*/&-/
- t lineno
- b
- :lineno
- N
- :loop
- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
- t loop
- s/-\n.*//
- ' >$as_me.lineno &&
- chmod +x "$as_me.lineno" ||
- { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
- { (exit 1); exit 1; }; }
-
- # Don't try to exec as it changes $[0], causing all sort of problems
- # (the dirname of $[0] is not the place where we might find the
- # original and so on. Autoconf is especially sensitive to this).
- . "./$as_me.lineno"
- # Exit status is that of the last command.
- exit
-}
-
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
- as_dirname=dirname
-else
- as_dirname=false
-fi
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
--n*)
- case `echo 'x\c'` in
- *c*) ECHO_T=' ';; # ECHO_T is single tab character.
- *) ECHO_C='\c';;
- esac;;
-*)
- ECHO_N='-n';;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
- rm -f conf$$.dir/conf$$.file
-else
- rm -f conf$$.dir
- mkdir conf$$.dir
-fi
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
- as_ln_s='ln -s'
- # ... but there are two gotchas:
- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
- # In both cases, we have to default to `cp -p'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
-elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
-else
- as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-if mkdir -p . 2>/dev/null; then
- as_mkdir_p=:
-else
- test -d ./-p && rmdir ./-p
- as_mkdir_p=false
-fi
-
-# Find out whether ``test -x'' works. Don't use a zero-byte file, as
-# systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
- as_executable_p="test -x"
-else
- as_executable_p=:
-fi
-rm -f conf$$.file
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-exec 6>&1
-
-# Save the log message, to keep $[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.
-ac_log="
-This file was extended by $as_me, which was
-generated by GNU Autoconf 2.60. Invocation command line was
-
- CONFIG_FILES = $CONFIG_FILES
- CONFIG_HEADERS = $CONFIG_HEADERS
- CONFIG_LINKS = $CONFIG_LINKS
- CONFIG_COMMANDS = $CONFIG_COMMANDS
- $ $0 $@
-
-on `(hostname || uname -n) 2>/dev/null | sed 1q`
-"
-
-# Files that config.status was made for.
-config_files=" Makefile"
-config_commands=" mkdir-vpath"
-
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
- -h, --help print this help, then exit
- -V, --version print version number, then exit
- -q, --quiet do not print progress messages
- -d, --debug don't remove temporary files
- --recheck update $as_me by reconfiguring in the same conditions
- --file=FILE[:TEMPLATE]
- instantiate the configuration file FILE
-
-Configuration files:
-$config_files
-
-Configuration commands:
-$config_commands
-
-Report bugs to <bug-autoconf@gnu.org>."
-
-ac_cs_version="\
-config.status
-configured by ./configure, generated by GNU Autoconf 2.60,
- with options \"'--enable-shared' '--with-apr=/usr/bin' '--with-apr-util=/usr/bin' 'CFLAGS=-fPIC'\"
-
-Copyright (C) 2006 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-
-ac_pwd='/home/konno/work/mod_chxj/mod_chxj/src/serf'
-srcdir='.'
-INSTALL='/usr/bin/install -c'
-# If no file are specified by the user, then we need to provide default
-# value. By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
- case $1 in
- --*=*)
- ac_option=`expr "X$1" : 'X\([^=]*\)='`
- ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
- ac_shift=:
- ;;
- *)
- ac_option=$1
- ac_optarg=$2
- ac_shift=shift
- ;;
- esac
-
- case $ac_option in
- # Handling of the options.
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- ac_cs_recheck=: ;;
- --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- echo "$ac_cs_version"; exit ;;
- --debug | --debu | --deb | --de | --d | -d )
- debug=: ;;
- --file | --fil | --fi | --f )
- $ac_shift
- CONFIG_FILES="$CONFIG_FILES $ac_optarg"
- ac_need_defaults=false;;
- --he | --h | --help | --hel | -h )
- echo "$ac_cs_usage"; exit ;;
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil | --si | --s)
- ac_cs_silent=: ;;
-
- # This is an error.
- -*) { echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2
- { (exit 1); exit 1; }; } ;;
-
- *) ac_config_targets="$ac_config_targets $1"
- ac_need_defaults=false ;;
-
- esac
- shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
- exec 6>/dev/null
- ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-if $ac_cs_recheck; then
- echo "running CONFIG_SHELL=/bin/sh /bin/sh ./configure " '--enable-shared' '--with-apr=/usr/bin' '--with-apr-util=/usr/bin' 'CFLAGS=-fPIC' $ac_configure_extra_args " --no-create --no-recursion" >&6
- CONFIG_SHELL=/bin/sh
- export CONFIG_SHELL
- exec /bin/sh "./configure" '--enable-shared' '--with-apr=/usr/bin' '--with-apr-util=/usr/bin' 'CFLAGS=-fPIC' $ac_configure_extra_args --no-create --no-recursion
-fi
-
-exec 5>>config.log
-{
- echo
- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
- echo "$ac_log"
-} >&5
-
-
-# Handling of arguments.
-for ac_config_target in $ac_config_targets
-do
- case $ac_config_target in
- "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "mkdir-vpath") CONFIG_COMMANDS="$CONFIG_COMMANDS mkdir-vpath" ;;
-
- *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
- { (exit 1); exit 1; }; };;
- esac
-done
-
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used. Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
-fi
-
-# Have a temporary directory for convenience. Make it in the build tree
-# simply because there is no reason against having it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Hook for its removal unless debugging.
-# Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to `$tmp'.
-$debug ||
-{
- tmp=
- trap 'exit_status=$?
- { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
-' 0
- trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-# Create a (secure) tmp directory for tmp files.
-
-{
- tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
- test -n "$tmp" && test -d "$tmp"
-} ||
-{
- tmp=./conf$$-$RANDOM
- (umask 077 && mkdir "$tmp")
-} ||
-{
- echo "$me: cannot create a temporary directory in ." >&2
- { (exit 1); exit 1; }
-}
-
-#
-# Set up the sed scripts for CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "$CONFIG_FILES"; then
-
-cat >"$tmp/subs-1.sed" <<\CEOF
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
-s,@SHELL@,|#_!!_#|/bin/sh,g
-s,@PATH_SEPARATOR@,|#_!!_#|:,g
-s,@PACKAGE_NAME@,|#_!!_#|,g
-s,@PACKAGE_TARNAME@,|#_!!_#|,g
-s,@PACKAGE_VERSION@,|#_!!_#|,g
-s,@PACKAGE_STRING@,|#_!!_#|,g
-s,@PACKAGE_BUGREPORT@,|#_!!_#|,g
-s,@exec_prefix@,|#_!!_#|${prefix},g
-s,@prefix@,|#_!!_#|/usr/local/serf,g
-s,@program_transform_name@,|#_!!_#|s\,x\,x\,,g
-s,@bindir@,|#_!!_#|${exec_prefix}/bin,g
-s,@sbindir@,|#_!!_#|${exec_prefix}/bin,g
-s,@libexecdir@,|#_!!_#|${exec_prefix}/modules,g
-s,@datarootdir@,|#_!!_#|${prefix}/share,g
-s,@datadir@,|#_!!_#|${prefix},g
-s,@sysconfdir@,|#_!!_#|${prefix}/conf,g
-s,@sharedstatedir@,|#_!!_#|${prefix}/com,g
-s,@localstatedir@,|#_!!_#|${prefix},g
-s,@includedir@,|#_!!_#|${prefix}/include/serf-${SERF_MAJOR_VERSION},g
-s,@oldincludedir@,|#_!!_#|/usr/include,g
-s,@docdir@,|#_!!_#|${datarootdir}/doc/${PACKAGE},g
-s,@infodir@,|#_!!_#|${datarootdir}/info,g
-s,@htmldir@,|#_!!_#|${docdir},g
-s,@dvidir@,|#_!!_#|${docdir},g
-s,@pdfdir@,|#_!!_#|${docdir},g
-s,@psdir@,|#_!!_#|${docdir},g
-s,@libdir@,|#_!!_#|${exec_prefix}/lib,g
-s,@localedir@,|#_!!_#|${datarootdir}/locale,g
-s,@mandir@,|#_!!_#|${prefix}/man,g
-s,@DEFS@,|#_!!_#|-DPACKAGE_NAME=\\"\\" -DPACKAGE_TARNAME=\\"\\" -DPACKAGE_VERSION=\\"\\" -DPACKAGE_STRING=\\"\\" -DPACKAGE_BUGREPORT=\\"\\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1,g
-s,@ECHO_C@,|#_!!_#|,g
-s,@ECHO_N@,|#_!!_#|-n,g
-s,@ECHO_T@,|#_!!_#|,g
-s,@LIBS@,|#_!!_#|,g
-s,@build_alias@,|#_!!_#|,g
-s,@host_alias@,|#_!!_#|,g
-s,@target_alias@,|#_!!_#|,g
-s,@mkdir_p@,|#_!!_#|mkdir -p,g
-s,@build@,|#_!!_#|i686-pc-linux-gnu,g
-s,@build_cpu@,|#_!!_#|i686,g
-s,@build_vendor@,|#_!!_#|pc,g
-s,@build_os@,|#_!!_#|linux-gnu,g
-s,@host@,|#_!!_#|i686-pc-linux-gnu,g
-s,@host_cpu@,|#_!!_#|i686,g
-s,@host_vendor@,|#_!!_#|pc,g
-s,@host_os@,|#_!!_#|linux-gnu,g
-s,@target@,|#_!!_#|i686-pc-linux-gnu,g
-s,@target_cpu@,|#_!!_#|i686,g
-s,@target_vendor@,|#_!!_#|pc,g
-s,@target_os@,|#_!!_#|linux-gnu,g
-s,@APR_LIBTOOL@,|#_!!_#|/usr/share/apr-1.0/build/libtool,g
-s,@APR_BINDIR@,|#_!!_#|/usr/bin,g
-s,@APR_INCLUDEDIR@,|#_!!_#|/usr/include/apr-1.0,g
-s,@APR_VERSION@,|#_!!_#|1.2.7,g
-s,@APR_CONFIG@,|#_!!_#|/usr/bin/apr-config,g
-s,@APU_BINDIR@,|#_!!_#|/usr/bin,g
-s,@APU_INCLUDEDIR@,|#_!!_#|/usr/include/apr-1.0,g
-s,@APU_VERSION@,|#_!!_#|1.2.7,g
-s,@APU_CONFIG@,|#_!!_#|/usr/bin/apu-1-config,g
-s,@CC@,|#_!!_#|i486-linux-gnu-gcc,g
-s,@CFLAGS@,|#_!!_#|-fPIC -pipe -Wall -g -O2 -pthread,g
-s,@LDFLAGS@,|#_!!_#| ,g
-s,@CPPFLAGS@,|#_!!_#| -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE,g
-s,@ac_ct_CC@,|#_!!_#|i486-linux-gnu-gcc,g
-s,@EXEEXT@,|#_!!_#|,g
-s,@OBJEXT@,|#_!!_#|o,g
-s,@CPP@,|#_!!_#|i486-linux-gnu-gcc -E,g
-s,@INSTALL_PROGRAM@,|#_!!_#|${INSTALL},g
-s,@INSTALL_SCRIPT@,|#_!!_#|${INSTALL},g
-s,@INSTALL_DATA@,|#_!!_#|${INSTALL} -m 644,g
-s,@SERF_MAJOR_VERSION@,|#_!!_#|0,g
-s,@SERF_DOTTED_VERSION@,|#_!!_#|0.1.2,g
-s,@SERF_BUILD_SRCLIB_DIRS@,|#_!!_#|,g
-s,@SERF_CLEAN_SRCLIB_DIRS@,|#_!!_#|,g
-s,@GREP@,|#_!!_#|/bin/grep,g
-s,@EGREP@,|#_!!_#|/bin/grep -E,g
-s,@SERF_LIBS@,|#_!!_#| /usr/lib/libaprutil-1.la /usr/lib/libapr-1.la -luuid -lrt -lcrypt -lpthread -ldl,g
-s,@LIBOBJS@,|#_!!_#|,g
-s,@LTLIBOBJS@,|#_!!_#|,g
-:end
-s/|#_!!_#|//g
-CEOF
-fi # test -n "$CONFIG_FILES"
-
-
-for ac_tag in :F $CONFIG_FILES :C $CONFIG_COMMANDS
-do
- case $ac_tag in
- :[FHLC]) ac_mode=$ac_tag; continue;;
- esac
- case $ac_mode$ac_tag in
- :[FHL]*:*);;
- :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
-echo "$as_me: error: Invalid tag $ac_tag." >&2;}
- { (exit 1); exit 1; }; };;
- :[FH]-) ac_tag=-:-;;
- :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
- esac
- ac_save_IFS=$IFS
- IFS=:
- set x $ac_tag
- IFS=$ac_save_IFS
- shift
- ac_file=$1
- shift
-
- case $ac_mode in
- :L) ac_source=$1;;
- :[FH])
- ac_file_inputs=
- for ac_f
- do
- case $ac_f in
- -) ac_f="$tmp/stdin";;
- *) # Look for the file first in the build tree, then in the source tree
- # (if the path is not absolute). The absolute path cannot be DOS-style,
- # because $ac_f cannot contain `:'.
- test -f "$ac_f" ||
- case $ac_f in
- [\\/$]*) false;;
- *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
- esac ||
- { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
-echo "$as_me: error: cannot find input file: $ac_f" >&2;}
- { (exit 1); exit 1; }; };;
- esac
- ac_file_inputs="$ac_file_inputs $ac_f"
- done
-
- # Let's still pretend it is `configure' which instantiates (i.e., don't
- # use $as_me), people would be surprised to read:
- # /* config.h. Generated by config.status. */
- configure_input="Generated from "`IFS=:
- echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
- if test x"$ac_file" != x-; then
- configure_input="$ac_file. $configure_input"
- { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
- fi
-
- case $ac_tag in
- *:-:* | *:-) cat >"$tmp/stdin";;
- esac
- ;;
- esac
-
- ac_dir=`$as_dirname -- "$ac_file" ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$ac_file" : 'X\(//\)[^/]' \| \
- X"$ac_file" : 'X\(//\)$' \| \
- X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$ac_file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- { as_dir="$ac_dir"
- case $as_dir in #(
- -*) as_dir=./$as_dir;;
- esac
- test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
- as_dirs=
- while :; do
- case $as_dir in #(
- *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
- *) as_qdir=$as_dir;;
- esac
- as_dirs="'$as_qdir' $as_dirs"
- as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$as_dir" : 'X\(//\)[^/]' \| \
- X"$as_dir" : 'X\(//\)$' \| \
- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-echo X"$as_dir" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- test -d "$as_dir" && break
- done
- test -z "$as_dirs" || eval "mkdir $as_dirs"
- } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
-echo "$as_me: error: cannot create directory $as_dir" >&2;}
- { (exit 1); exit 1; }; }; }
- ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
- ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
- # A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
- case $ac_top_builddir_sub in
- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
- esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
- .) # We are building in place.
- ac_srcdir=.
- ac_top_srcdir=$ac_top_builddir_sub
- ac_abs_top_srcdir=$ac_pwd ;;
- [\\/]* | ?:[\\/]* ) # Absolute name.
- ac_srcdir=$srcdir$ac_dir_suffix;
- ac_top_srcdir=$srcdir
- ac_abs_top_srcdir=$srcdir ;;
- *) # Relative name.
- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
- ac_top_srcdir=$ac_top_build_prefix$srcdir
- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
-
- case $ac_mode in
- :F)
- #
- # CONFIG_FILE
- #
-
- case $INSTALL in
- [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
- esac
-# If the template does not know about datarootdir, expand it.
-# FIXME: This hack should be removed a few years after 2.60.
-ac_datarootdir_hack=; ac_datarootdir_seen=
-
-case `sed -n '/datarootdir/ {
- p
- q
-}
-/@datadir@/p
-/@docdir@/p
-/@infodir@/p
-/@localedir@/p
-/@mandir@/p
-' $ac_file_inputs` in
-*datarootdir*) ac_datarootdir_seen=yes;;
-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
- ac_datarootdir_hack='
- s&@datadir@&${prefix}&g
- s&@docdir@&${datarootdir}/doc/${PACKAGE}&g
- s&@infodir@&${datarootdir}/info&g
- s&@localedir@&${datarootdir}/locale&g
- s&@mandir@&${prefix}/man&g
- s&\${datarootdir}&${prefix}/share&g' ;;
-esac
- sed "/^[ ]*VPATH[ ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[ ]*\):*/\1/
-s/:*$//
-s/^[^=]*=[ ]*$//
-}
-
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s&@configure_input@&$configure_input&;t t
-s&@top_builddir@&$ac_top_builddir_sub&;t t
-s&@srcdir@&$ac_srcdir&;t t
-s&@abs_srcdir@&$ac_abs_srcdir&;t t
-s&@top_srcdir@&$ac_top_srcdir&;t t
-s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
-s&@builddir@&$ac_builddir&;t t
-s&@abs_builddir@&$ac_abs_builddir&;t t
-s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
-s&@INSTALL@&$ac_INSTALL&;t t
-$ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
-
-test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
- { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
- { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
- { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&5
-echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined. Please make sure it is defined." >&2;}
-
- rm -f "$tmp/stdin"
- case $ac_file in
- -) cat "$tmp/out"; rm -f "$tmp/out";;
- *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
- esac
- ;;
-
-
- :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
-echo "$as_me: executing $ac_file commands" >&6;}
- ;;
- esac
-
-
- case $ac_file$ac_mode in
- "mkdir-vpath":C) make mkdir-vpath ;;
-
- esac
-done # for ac_tag
-
-
-{ (exit 0); exit 0; }
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.60.
+# Generated by GNU Autoconf 2.61.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
## M4sh Initialization. ##
## --------------------- ##
-# Be Bourne compatible
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
+
# PATH needs CR
else
as_candidate_shells=
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
# Try only shells that exist, to save several forks.
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
{ ("$as_shell") 2> /dev/null <<\_ASEOF
-# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
:
_ASEOF
CONFIG_SHELL=$as_shell
as_have_required=yes
if { "$as_shell" 2> /dev/null <<\_ASEOF
-# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
:
(as_func_return () {
as_mkdir_p=false
fi
-# Find out whether ``test -x'' works. Don't use a zero-byte file, as
-# systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
- as_executable_p="test -x"
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
else
- as_executable_p=:
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
fi
-rm -f conf$$.file
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
-#if HAVE_SYS_TYPES_H
+#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_STAT_H
+#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
-#if STDC_HEADERS
+#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
-# if HAVE_STDLIB_H
+# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
-#if HAVE_STRINGS_H
+#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
-#if HAVE_INTTYPES_H
+#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
-#if HAVE_STDINT_H
+#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
-#if HAVE_UNISTD_H
+#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
CC
CFLAGS
LDFLAGS
+LIBS
CPPFLAGS
CPP'
-disable-* | --disable-*)
ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid feature name: $ac_feature" >&2
{ (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
eval enable_$ac_feature=no ;;
-docdir | --docdir | --docdi | --doc | --do)
-enable-* | --enable-*)
ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid feature name: $ac_feature" >&2
{ (exit 1); exit 1; }; }
- ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
eval enable_$ac_feature=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
-with-* | --with-*)
ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid package name: $ac_package" >&2
{ (exit 1); exit 1; }; }
- ac_package=`echo $ac_package| sed 's/-/_/g'`
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
eval with_$ac_package=\$ac_optarg ;;
-without-* | --without-*)
ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
- expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid package name: $ac_package" >&2
{ (exit 1); exit 1; }; }
- ac_package=`echo $ac_package | sed 's/-/_/g'`
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
eval with_$ac_package=no ;;
--x)
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.60
+generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.60. Invocation command line was
+generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
+
+
# Check whether --enable-layout was given.
if test "${enable_layout+set}" = set; then
enableval=$enable_layout;
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="gcc"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_ac_ct_CC="$ac_prog"
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
# in a Makefile. We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
-for ac_file in $ac_files
+for ac_file in $ac_files ''
do
test -f "$ac_file" || continue
case $ac_file in
test "$ac_cv_exeext" = no && ac_cv_exeext=
else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
fi
ac_exeext=$ac_cv_exeext
-{ echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6; }
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_compiler_gnu=yes
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cc_g=yes
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
:
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cc_g=yes
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_prog_cc_c89=$ac_arg
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
:
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
# Broken: success on invalid input.
continue
else
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
:
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
# Broken: success on invalid input.
continue
else
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
if test $ac_prog = install &&
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
for ac_prog in grep ggrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
# Check for GNU ac_path_GREP and select it if it is found.
# Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_cv_header_stdc=yes
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
eval "$as_ac_Header=yes"
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; } &&
- { ac_try='test -s conftest.$ac_objext'
- { (case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } >/dev/null; then
- if test -s conftest.err; then
- ac_cpp_err=$ac_c_preproc_warn_flag
- ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
- else
- ac_cpp_err=
- fi
-else
- ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
## M4sh Initialization. ##
## --------------------- ##
-# Be Bourne compatible
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
- case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
+
+
# PATH needs CR
as_mkdir_p=false
fi
-# Find out whether ``test -x'' works. Don't use a zero-byte file, as
-# systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
- as_executable_p="test -x"
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
else
- as_executable_p=:
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
fi
-rm -f conf$$.file
+as_executable_p=$as_test_x
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.60. Invocation command line was
+generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
Usage: $0 [OPTIONS] [FILE]...
-h, --help print this help, then exit
- -V, --version print version number, then exit
+ -V, --version print version number and configuration settings, then exit
-q, --quiet do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.60,
+configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
Copyright (C) 2006 Free Software Foundation, Inc.
* limitations under the License.
*/
-#include <stdlib.h> /* ### for abort() */
-
#include <apr_pools.h>
#include <apr_poll.h>
#include <apr_version.h>
struct serf_request_t *next;
};
+typedef struct serf_pollset_t {
+ /* the set of connections to poll */
+ apr_pollset_t *pollset;
+} serf_pollset_t;
+
struct serf_context_t {
/* the pool used for self and for other allocations */
apr_pool_t *pool;
- /* the set of connections to poll */
- apr_pollset_t *pollset;
+ 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;
};
struct serf_connection_t {
void *setup_baton;
serf_connection_closed_t closed;
void *closed_baton;
+
+ /* Max. number of outstanding requests. */
+ unsigned int max_outstanding_requests;
+
+ /* Host info. */
+ const char *host_url;
+ apr_uri_t host_info;
};
/* cleanup for sockets */
apr_status_t status;
apr_pollfd_t desc = { 0 };
+ if (!conn->skt) {
+ return APR_SUCCESS;
+ }
+
/* Remove the socket from the poll set. */
desc.desc_type = APR_POLL_SOCKET;
desc.desc.s = conn->skt;
desc.reqevents = conn->reqevents;
- status = apr_pollset_remove(ctx->pollset, &desc);
+ status = ctx->pollset_rm(ctx->pollset_baton,
+ &desc, conn);
if (status && !APR_STATUS_IS_NOTFOUND(status))
return status;
else {
serf_request_t *request = conn->requests;
- if (conn->probable_keepalive_limit &&
- conn->completed_requests > conn->probable_keepalive_limit) {
+ if ((conn->probable_keepalive_limit &&
+ conn->completed_requests > conn->probable_keepalive_limit) ||
+ (conn->max_outstanding_requests &&
+ conn->completed_requests - conn->completed_responses >=
+ conn->max_outstanding_requests)) {
/* we wouldn't try to write any way right now. */
}
else {
}
}
- desc.client_data = conn;
-
/* save our reqevents, so we can pass it in to remove later. */
conn->reqevents = desc.reqevents;
/* Note: even if we don't want to read/write this socket, we still
* want to poll it for hangups and errors.
*/
- return apr_pollset_add(ctx->pollset, &desc);
+ return ctx->pollset_add(ctx->pollset_baton,
+ &desc, conn);
}
#ifdef SERF_DEBUG_BUCKET_USE
serf_connection_t *conn = GET_CONN(ctx, i);
apr_status_t status;
apr_socket_t *skt;
+ apr_sockaddr_t *serv_addr;
conn->seen_in_pollset = 0;
/* Configured. Store it into the connection now. */
conn->skt = skt;
+ /* Do we have to connect to a proxy server? */
+ if (ctx->proxy_address)
+ serv_addr = ctx->proxy_address;
+ else
+ serv_addr = conn->address;
+
/* Now that the socket is set up, let's connect it. This should
* return immediately.
*/
if ((status = apr_socket_connect(skt,
- conn->address)) != APR_SUCCESS) {
+ serv_addr)) != APR_SUCCESS) {
if (!APR_STATUS_IS_EINPROGRESS(status))
return status;
}
return APR_SUCCESS;
}
+/* Read the 'Connection' header from the response. Return SERF_ERROR_CLOSING if
+ * the header contains value 'close' indicating the server is closing the
+ * connection right after this response.
+ * Otherwise returns APR_SUCCESS.
+ */
+static apr_status_t is_conn_closing(serf_bucket_t *response)
+{
+ serf_bucket_t *hdrs;
+ const char *val;
+
+ hdrs = serf_bucket_response_get_headers(response);
+ val = serf_bucket_headers_get(hdrs, "Connection");
+ if (val && strcasecmp("close", val) == 0)
+ {
+ return SERF_ERROR_CLOSING;
+ }
+
+ return APR_SUCCESS;
+}
+
static void link_requests(serf_request_t **list, serf_request_t **tail,
serf_request_t *request)
{
desc.desc.s = conn->skt;
desc.reqevents = conn->reqevents;
- return apr_pollset_remove(ctx->pollset, &desc);
+ return ctx->pollset_rm(ctx->pollset_baton,
+ &desc, conn);
}
static apr_status_t reset_connection(serf_connection_t *conn,
old_reqs = conn->requests;
held_reqs = conn->hold_requests;
held_reqs_tail = conn->hold_requests_tail;
-
+
if (conn->closing) {
conn->hold_requests = NULL;
conn->hold_requests_tail = NULL;
return APR_SUCCESS;
}
+/**
+ * Callback function (implements serf_progress_t). Takes a number of bytes
+ * read @a read and bytes written @a written, adds those to the total for this
+ * context and notifies an interested party (if any).
+ */
+static void serf_context_progress_delta(
+ void *progress_baton,
+ apr_off_t read,
+ apr_off_t written)
+{
+ serf_context_t *ctx = progress_baton;
+
+ ctx->progress_read += read;
+ ctx->progress_written += written;
+
+ if (ctx->progress_func)
+ ctx->progress_func(ctx->progress_baton,
+ ctx->progress_read,
+ ctx->progress_written);
+}
+
static apr_status_t socket_writev(serf_connection_t *conn)
{
apr_size_t written;
if (len == written) {
conn->vec_len = 0;
}
+
+ /* Log progress information */
+ serf_context_progress_delta(conn->ctx, 0, written);
}
return status;
apr_status_t status;
apr_status_t read_status;
+ if (conn->max_outstanding_requests &&
+ conn->completed_requests -
+ conn->completed_responses >= conn->max_outstanding_requests) {
+ /* backoff for now. */
+ return APR_SUCCESS;
+ }
+
/* If we have unwritten data, then write what we can. */
while (conn->vec_len) {
status = socket_writev(conn);
{
apr_status_t status;
apr_pool_t *tmppool;
+ int close_connection = FALSE;
/* Whatever is coming in on the socket corresponds to the first request
* on our chain.
continue;
}
- if (!APR_STATUS_IS_EOF(status) && status != SERF_ERROR_CLOSING) {
+ close_connection = is_conn_closing(request->resp_bkt);
+
+ if (!APR_STATUS_IS_EOF(status) &&
+ close_connection != SERF_ERROR_CLOSING) {
/* Whether success, or an error, there is no more to do unless
* this request has been completed.
*/
conn->requests_tail = NULL;
}
+ conn->completed_responses++;
+
/* This means that we're being advised that the connection is done. */
- if (status == SERF_ERROR_CLOSING) {
+ if (close_connection == SERF_ERROR_CLOSING) {
reset_connection(conn, 1);
- status = APR_SUCCESS;
+ if (APR_STATUS_IS_EOF(status))
+ status = APR_SUCCESS;
goto error;
}
- conn->completed_responses++;
-
/* The server is suddenly deciding to serve more responses than we've
* seen before.
*
return APR_SUCCESS;
}
-SERF_DECLARE(serf_context_t *) serf_context_create(apr_pool_t *pool)
+
+static apr_status_t pollset_add(void *user_baton,
+ apr_pollfd_t *pfd,
+ void *serf_baton)
+{
+ serf_pollset_t *s = (serf_pollset_t*)user_baton;
+ pfd->client_data = serf_baton;
+ return apr_pollset_add(s->pollset, pfd);
+}
+
+static apr_status_t pollset_rm(void *user_baton,
+ apr_pollfd_t *pfd,
+ void *serf_baton)
+{
+ serf_pollset_t *s = (serf_pollset_t*)user_baton;
+ pfd->client_data = serf_baton;
+ return apr_pollset_remove(s->pollset, pfd);
+}
+
+
+SERF_DECLARE(void) serf_config_proxy(serf_context_t *ctx,
+ apr_sockaddr_t *address)
+{
+ ctx->proxy_address = address;
+}
+
+SERF_DECLARE(serf_context_t *) serf_context_create_ex(void *user_baton,
+ serf_socket_add_t addf,
+ serf_socket_remove_t rmf,
+ apr_pool_t *pool)
{
serf_context_t *ctx = apr_pcalloc(pool, sizeof(*ctx));
ctx->pool = pool;
- /* build the pollset with a (default) number of connections */
- (void) apr_pollset_create(&ctx->pollset, MAX_CONN, pool, 0);
+ if (user_baton != NULL) {
+ ctx->pollset_baton = user_baton;
+ ctx->pollset_add = addf;
+ ctx->pollset_rm = rmf;
+ }
+ else {
+ /* build the pollset with a (default) number of connections */
+ serf_pollset_t *ps = apr_pcalloc(pool, sizeof(*ps));
+ (void) apr_pollset_create(&ps->pollset, MAX_CONN, pool, 0);
+ ctx->pollset_baton = ps;
+ ctx->pollset_add = pollset_add;
+ ctx->pollset_rm = pollset_rm;
+ }
/* default to a single connection since that is the typical case */
ctx->conns = apr_array_make(pool, 1, sizeof(serf_connection_t *));
+ /* Initialize progress status */
+ ctx->progress_read = 0;
+ ctx->progress_written = 0;
+
return ctx;
}
+SERF_DECLARE(serf_context_t *) serf_context_create(apr_pool_t *pool)
+{
+ return serf_context_create_ex(NULL, NULL, NULL, pool);
+}
+
+SERF_DECLARE(apr_status_t) serf_context_prerun(serf_context_t *ctx)
+{
+ apr_status_t status = APR_SUCCESS;
+ if ((status = open_connections(ctx)) != APR_SUCCESS)
+ return status;
+
+ if ((status = check_dirty_pollsets(ctx)) != APR_SUCCESS)
+ return status;
+ return status;
+}
+
+SERF_DECLARE(apr_status_t) serf_event_trigger(serf_context_t *s,
+ void *serf_baton,
+ const apr_pollfd_t *desc)
+{
+ apr_status_t status = APR_SUCCESS;
+
+ serf_connection_t *conn = serf_baton;
+
+ /* apr_pollset_poll() can return a conn multiple times... */
+ if ((conn->seen_in_pollset & desc->rtnevents) != 0 ||
+ (conn->seen_in_pollset & APR_POLLHUP) != 0) {
+ return APR_SUCCESS;
+ }
+
+ conn->seen_in_pollset |= desc->rtnevents;
+
+ if ((status = process_connection(conn,
+ desc->rtnevents)) != APR_SUCCESS) {
+ return status;
+ }
+
+ return status;
+}
+
SERF_DECLARE(apr_status_t) serf_context_run(serf_context_t *ctx,
apr_short_interval_time_t duration,
apr_pool_t *pool)
apr_status_t status;
apr_int32_t num;
const apr_pollfd_t *desc;
+ serf_pollset_t *ps = (serf_pollset_t*)ctx->pollset_baton;
- if ((status = open_connections(ctx)) != APR_SUCCESS)
- return status;
-
- if ((status = check_dirty_pollsets(ctx)) != APR_SUCCESS)
+ if ((status = serf_context_prerun(ctx)) != APR_SUCCESS) {
return status;
+ }
- if ((status = apr_pollset_poll(ctx->pollset, duration, &num,
+ if ((status = apr_pollset_poll(ps->pollset, duration, &num,
&desc)) != APR_SUCCESS) {
/* ### do we still need to dispatch stuff here?
### look at the potential return codes. map to our defined
while (num--) {
serf_connection_t *conn = desc->client_data;
- /* apr_pollset_poll() can return a conn multiple times... */
- if ((conn->seen_in_pollset & desc->rtnevents) != 0 ||
- (conn->seen_in_pollset & APR_POLLHUP) != 0) {
- continue;
- }
- conn->seen_in_pollset |= desc->rtnevents;
-
- if ((status = process_connection(conn,
- desc++->rtnevents)) != APR_SUCCESS) {
- /* ### what else to do? */
+ status = serf_event_trigger(ctx, conn, desc);
+ if (status) {
return status;
}
+
+ desc++;
}
return APR_SUCCESS;
}
+SERF_DECLARE(void) serf_context_set_progress_cb(
+ serf_context_t *ctx,
+ const serf_progress_t progress_func,
+ void *progress_baton)
+{
+ ctx->progress_func = progress_func;
+ ctx->progress_baton = progress_baton;
+}
SERF_DECLARE(serf_connection_t *) serf_connection_create(
serf_context_t *ctx,
conn->closed_baton = closed_baton;
conn->pool = pool;
conn->allocator = serf_bucket_allocator_create(pool, NULL, NULL);
+ conn->stream = NULL;
/* Create a subpool for our connection. */
apr_pool_create(&conn->skt_pool, conn->pool);
return conn;
}
+SERF_DECLARE(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)
+{
+ apr_status_t status;
+ serf_connection_t *c;
+ apr_sockaddr_t *host_address;
+
+ /* Parse the url, store the address of the server. */
+ status = apr_sockaddr_info_get(&host_address,
+ host_info.hostname,
+ APR_UNSPEC, host_info.port, 0, pool);
+ if (status)
+ return status;
+
+ c = serf_connection_create(ctx, host_address, setup, setup_baton,
+ closed, closed_baton, pool);
+
+ /* We're not interested in the path following the hostname. */
+ c->host_url = apr_uri_unparse(c->pool,
+ &host_info,
+ APR_URI_UNP_OMITPATHINFO);
+ c->host_info = host_info;
+
+ *conn = c;
+
+ return status;
+}
+
SERF_DECLARE(apr_status_t) serf_connection_reset(
serf_connection_t *conn)
{
(*conn->closed)(conn, conn->closed_baton, status,
conn->pool);
}
+ conn->skt = NULL;
}
if (conn->stream != NULL) {
serf_bucket_destroy(conn->stream);
return APR_NOTFOUND;
}
+SERF_DECLARE(void)
+serf_connection_set_max_outstanding_requests(serf_connection_t *conn,
+ unsigned int max_requests)
+{
+ conn->max_outstanding_requests = max_requests;
+}
+
SERF_DECLARE(serf_request_t *) serf_connection_request_create(
serf_connection_t *conn,
serf_request_setup_t setup,
return request;
}
+SERF_DECLARE(serf_request_t *) serf_connection_priority_request_create(
+ serf_connection_t *conn,
+ serf_request_setup_t setup,
+ void *setup_baton)
+{
+ serf_request_t *request;
+ serf_request_t *iter, *prev;
+
+ request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
+ request->conn = conn;
+ request->setup = setup;
+ request->setup_baton = setup_baton;
+ request->handler = NULL;
+ request->respool = NULL;
+ request->req_bkt = NULL;
+ request->resp_bkt = NULL;
+ request->next = NULL;
+
+ /* Link the new request after the last written request, but before all
+ upcoming requests. */
+ if (conn->closing) {
+ iter = conn->hold_requests;
+ }
+ else {
+ iter = conn->requests;
+ }
+ prev = NULL;
+
+ /* Find a request that has data which needs to be delivered. */
+ while (iter != NULL && iter->req_bkt == NULL && iter->setup == NULL) {
+ prev = iter;
+ iter = iter->next;
+ }
+
+ if (prev) {
+ request->next = iter;
+ prev->next = request;
+ } else {
+ request->next = iter;
+ if (conn->closing) {
+ conn->hold_requests = request;
+ }
+ else {
+ conn->requests = request;
+ }
+ }
+
+ if (! conn->closing) {
+ /* Ensure our pollset becomes writable in context run */
+ conn->ctx->dirty_pollset = 1;
+ conn->dirty_conn = 1;
+ }
+
+ return request;
+}
SERF_DECLARE(apr_status_t) serf_request_cancel(serf_request_t *request)
{
request->handler = handler;
request->handler_baton = handler_baton;
}
+
+SERF_DECLARE(serf_bucket_t *) serf_context_bucket_socket_create(
+ serf_context_t *ctx,
+ apr_socket_t *skt,
+ serf_bucket_alloc_t *allocator)
+{
+ serf_bucket_t *bucket = serf_bucket_socket_create(skt, allocator);
+
+ /* Use serf's default bytes read/written callback */
+ serf_bucket_socket_set_read_progress_cb(bucket,
+ serf_context_progress_delta,
+ ctx);
+
+ return bucket;
+}
+
+SERF_DECLARE(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)
+{
+ serf_bucket_t *req_bkt, *hdrs_bkt;
+
+ req_bkt = serf_bucket_request_create(method, uri, body, allocator);
+ hdrs_bkt = serf_bucket_request_get_headers(req_bkt);
+
+ /* Proxy? */
+ if (request->conn->ctx->proxy_address && request->conn->host_url)
+ serf_bucket_request_set_root(req_bkt, request->conn->host_url);
+
+ if (request->conn->host_info.hostname)
+ serf_bucket_headers_setn(hdrs_bkt, "Host",
+ request->conn->host_info.hostname);
+
+ return req_bkt;
+}
#include <apr_pools.h>
#include <apr_network_io.h>
#include <apr_time.h>
+#include <apr_poll.h>
+#include <apr_uri.h>
#include "serf_declare.h"
*/
SERF_DECLARE(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_DECLARE(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.
+ */
+SERF_DECLARE(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". */
apr_pool_t *pool);
+SERF_DECLARE(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.
+ */
+SERF_DECLARE(void) serf_context_set_progress_cb(
+ serf_context_t *ctx,
+ const serf_progress_t progress_func,
+ void *progress_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.
+ */
+SERF_DECLARE(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);
+
+/**
* Reset the connection, but re-open the socket again.
*/
SERF_DECLARE(apr_status_t) serf_connection_reset(
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.
+ */
+SERF_DECLARE(void)
+serf_connection_set_max_outstanding_requests(serf_connection_t *conn,
+ unsigned int max_requests);
+
+/**
* Setup the @a request for delivery on its connection.
*
* Right before this is invoked, @a pool will be built within the
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_DECLARE(serf_request_t *) serf_connection_priority_request_create(
+ serf_connection_t *conn,
+ serf_request_setup_t setup,
+ void *setup_baton);
+
+/**
* Cancel the request specified by the @a request object.
*
* If the request has been scheduled for delivery, then its response
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.
+ */
+SERF_DECLARE(void) serf_config_proxy(
+ serf_context_t *ctx,
+ apr_sockaddr_t *address);
+
/* ### 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_DECLARE(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.
+ *
+ * If the host_url and/or user_agent options are set on the connection,
+ * headers 'Host' and/or 'User-Agent' will be set on the request message.
+ */
+SERF_DECLARE(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);
+
/** @} */
/* Version info */
#define SERF_MAJOR_VERSION 0
-#define SERF_MINOR_VERSION 1
-#define SERF_PATCH_VERSION 2
+#define SERF_MINOR_VERSION 2
+#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
-#**** serf Win32 -*- Makefile -*- ********************************************\r
-#\r
-# Define DEBUG_BUILD to create a debug version of the library.\r
-\r
-!IF "$(OS)" == "Windows_NT"\r
-NULL=\r
-!ELSE\r
-NULL=nul\r
-!ENDIF\r
-\r
-CFLAGS = /Zi /W3 /EHsc /I "./"\r
-\r
-!IF "$(DEBUG_BUILD)" == ""\r
-INTDIR = Release\r
-CFLAGS = /MD /O2 /D "NDEBUG" $(CFLAGS)\r
-STATIC_LIB = $(INTDIR)\serf.lib\r
-!ELSE\r
-INTDIR = Debug\r
-CFLAGS = /MDd /Od /W3 /Gm /D "_DEBUG" $(CFLAGS)\r
-STATIC_LIB = $(INTDIR)\serf.lib\r
-!ENDIF\r
-\r
-########\r
-# Support for OpenSSL integration\r
-!IF "$(OPENSSL_SRC)" == ""\r
-!ERROR OpenSSL is required. Please define OPENSSL_SRC.\r
-!ELSE\r
-OPENSSL_FLAGS = /I "$(OPENSSL_SRC)\inc32"\r
-!ENDIF\r
-\r
-!IF "$(HTTPD_SRC)" != ""\r
-!IF "$(APR_SRC)" == ""\r
-APR_SRC=$(HTTPD_SRC)\srclib\apr\r
-!ENDIF\r
-\r
-!IF "$(APRUTIL_SRC)" == ""\r
-APRUTIL_SRC=$(HTTPD_SRC)\srclib\apr-util\r
-!ENDIF\r
-\r
-!ENDIF\r
-\r
-########\r
-# APR\r
-!IF "$(APR_SRC)" == ""\r
-!ERROR APR is required. Please define APR_SRC or HTTPD_SRC.\r
-!ENDIF\r
-\r
-APR_FLAGS = /I "$(APR_SRC)\include"\r
-!IF [IF EXIST "$(APR_SRC)\$(INTDIR)\libapr-1.lib" exit 1] == 1\r
-APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr-1.lib"\r
-!ELSE\r
-APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr.lib"\r
-!ENDIF\r
-\r
-########\r
-# APR Util\r
-!IF "$(APRUTIL_SRC)" == ""\r
-!ERROR APR-Util is required. Please define APRUTIL_SRC or HTTPD_SRC.\r
-!ENDIF\r
-\r
-APRUTIL_FLAGS = /I "$(APRUTIL_SRC)\include"\r
-!IF [IF EXIST "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib" exit 1] == 1\r
-APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib"\r
-!ELSE\r
-APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil.lib"\r
-!ENDIF\r
-\r
-########\r
-# Support for zlib integration\r
-!IF "$(ZLIB_SRC)" == ""\r
-!ERROR ZLib is required. Please define ZLIB_SRC.\r
-!ELSE\r
-ZLIB_FLAGS = /I "$(ZLIB_SRC)"\r
-!IF "$(ZLIB_DLL)" == ""\r
-!IF "$(ZLIB_LIBDIR)" == ""\r
-!IF "$(DEBUG_BUILD)" == ""\r
-ZLIB_LIBS = "$(ZLIB_SRC)\zlibstat.lib"\r
-!ELSE\r
-ZLIB_LIBS = "$(ZLIB_SRC)\zlibstatD.lib"\r
-!ENDIF\r
-!ELSE\r
-ZLIB_LIBS = "$(ZLIB_LIBDIR)\x86\ZlibStat$(INTDIR)\zlibstat.lib"\r
-ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_WINAPI\r
-!ENDIF\r
-!ELSE\r
-ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_DLL\r
-ZLIB_LIBS = "$(ZLIB_SRC)\zlibdll.lib"\r
-!ENDIF\r
-!ENDIF\r
-\r
-\r
-# Exclude stuff we don't need from the Win32 headers\r
-WIN32_DEFS = /D WIN32 /D WIN32_LEAN_AND_MEAN /D NOUSER /D NOGDI /D NONLS /D NOCRYPT\r
-\r
-CPP=cl.exe\r
-CPP_PROJ = /c /nologo $(CFLAGS) $(WIN32_DEFS) $(EXPAT_FLAGS) $(APR_FLAGS) $(APRUTIL_FLAGS) $(OPENSSL_FLAGS) $(ZLIB_FLAGS) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\r
-LIB32=link.exe\r
-LIB32_FLAGS=/nologo\r
-\r
-LIB32_OBJS= \\r
- "$(INTDIR)\aggregate_buckets.obj" \\r
- "$(INTDIR)\context.obj" \\r
- "$(INTDIR)\allocator.obj" \\r
- "$(INTDIR)\barrier_buckets.obj" \\r
- "$(INTDIR)\buckets.obj" \\r
- "$(INTDIR)\chunk_buckets.obj" \\r
- "$(INTDIR)\dechunk_buckets.obj" \\r
- "$(INTDIR)\deflate_buckets.obj" \\r
- "$(INTDIR)\file_buckets.obj" \\r
- "$(INTDIR)\headers_buckets.obj" \\r
- "$(INTDIR)\limit_buckets.obj" \\r
- "$(INTDIR)\mmap_buckets.obj" \\r
- "$(INTDIR)\request_buckets.obj" \\r
- "$(INTDIR)\response_buckets.obj" \\r
- "$(INTDIR)\simple_buckets.obj" \\r
- "$(INTDIR)\socket_buckets.obj" \\r
- "$(INTDIR)\ssl_buckets.obj" \\r
-\r
-!IFDEF OPENSSL_STATIC\r
-LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32\libeay32.lib" \\r
- "$(OPENSSL_SRC)\out32\ssleay32.lib"\r
-!ELSE\r
-LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32dll\libeay32.lib" \\r
- "$(OPENSSL_SRC)\out32dll\ssleay32.lib"\r
-!ENDIF\r
-\r
-LIB32_OBJS = $(LIB32_OBJS) $(APR_LIBS) $(APRUTIL_LIBS) $(ZLIB_LIBS) \r
-\r
-ALL: INTDIR $(STATIC_LIB) TESTS\r
- \r
-\r
-CLEAN:\r
- -@erase /q "$(INTDIR)" >nul\r
-\r
-INTDIR:\r
- -@if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"\r
-\r
-TESTS: $(STATIC_LIB) $(INTDIR)\serf_response.exe $(INTDIR)\serf_get.exe \\r
- $(INTDIR)\serf_request.exe\r
-\r
-CHECK: INTDIR TESTS\r
- $(INTDIR)\serf_response.exe test\testcases\simple.response\r
- $(INTDIR)\serf_response.exe test\testcases\chunked-empty.response\r
- $(INTDIR)\serf_response.exe test\testcases\chunked.response\r
- $(INTDIR)\serf_response.exe test\testcases\chunked-trailers.response\r
- $(INTDIR)\serf_response.exe test\testcases\deflate.response\r
- \r
-"$(STATIC_LIB)": INTDIR $(LIB32_OBJS)\r
- $(LIB32) -lib @<<\r
- $(LIB32_FLAGS) $(LIB32_OBJS) /OUT:"$(STATIC_LIB)"\r
-<<\r
-\r
-\r
-.c{$(INTDIR)}.obj:\r
- $(CPP) @<<\r
- $(CPP_PROJ) $<\r
-<<\r
-\r
-{buckets}.c{$(INTDIR)}.obj:\r
- $(CPP) @<<\r
- $(CPP_PROJ) $<\r
-<<\r
-\r
-{test}.c{$(INTDIR)}.obj: \r
- $(CPP) @<<\r
- $(CPP_PROJ) $<\r
-<<\r
-\r
-$(INTDIR)\serf_response.exe: $(INTDIR)\serf_response.obj $(STATIC_LIB)\r
- $(LIB32) /DEBUG $(INTDIR)\serf_response.obj /OUT:$(INTDIR)\serf_response.exe $(LIB32_FLAGS) $(STATIC_LIB)\r
-\r
-$(INTDIR)\serf_get.exe: $(INTDIR)\serf_get.obj $(STATIC_LIB)\r
- $(LIB32) $(INTDIR)\serf_get.obj /OUT:$(INTDIR)\serf_get.exe $(LIB32_FLAGS) $(STATIC_LIB)\r
-\r
-$(INTDIR)\serf_request.exe: $(INTDIR)\serf_request.obj $(STATIC_LIB)\r
- $(LIB32) $(INTDIR)\serf_request.obj /OUT:$(INTDIR)\serf_request.exe $(LIB32_FLAGS) $(STATIC_LIB)\r
-\r
-$(INTDIR)\serf_spider.exe: $(INTDIR)\serf_spider.obj $(STATIC_LIB)\r
- $(LIB32) $(INTDIR)\serf_spider.obj /OUT:$(INTDIR)\serf_spider.exe $(LIB32_FLAGS) $(STATIC_LIB)\r
+#**** serf Win32 -*- Makefile -*- ********************************************
+#
+# Define DEBUG_BUILD to create a debug version of the library.
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CFLAGS = /Zi /W3 /EHsc /I "./"
+
+!IF "$(DEBUG_BUILD)" == ""
+INTDIR = Release
+CFLAGS = /MD /O2 /D "NDEBUG" $(CFLAGS)
+STATIC_LIB = $(INTDIR)\serf.lib
+!ELSE
+INTDIR = Debug
+CFLAGS = /MDd /Od /W3 /Gm /D "_DEBUG" $(CFLAGS)
+STATIC_LIB = $(INTDIR)\serf.lib
+!ENDIF
+
+########
+# Support for OpenSSL integration
+!IF "$(OPENSSL_SRC)" == ""
+!ERROR OpenSSL is required. Please define OPENSSL_SRC.
+!ELSE
+OPENSSL_FLAGS = /I "$(OPENSSL_SRC)\inc32"
+!ENDIF
+
+!IF "$(HTTPD_SRC)" != ""
+!IF "$(APR_SRC)" == ""
+APR_SRC=$(HTTPD_SRC)\srclib\apr
+!ENDIF
+
+!IF "$(APRUTIL_SRC)" == ""
+APRUTIL_SRC=$(HTTPD_SRC)\srclib\apr-util
+!ENDIF
+
+!ENDIF
+
+########
+# APR
+!IF "$(APR_SRC)" == ""
+!ERROR APR is required. Please define APR_SRC or HTTPD_SRC.
+!ENDIF
+
+APR_FLAGS = /I "$(APR_SRC)\include"
+!IF [IF EXIST "$(APR_SRC)\$(INTDIR)\libapr-1.lib" exit 1] == 1
+APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr-1.lib"
+!ELSE
+APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr.lib"
+!ENDIF
+
+########
+# APR Util
+!IF "$(APRUTIL_SRC)" == ""
+!ERROR APR-Util is required. Please define APRUTIL_SRC or HTTPD_SRC.
+!ENDIF
+
+APRUTIL_FLAGS = /I "$(APRUTIL_SRC)\include"
+!IF [IF EXIST "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib" exit 1] == 1
+APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib"
+!ELSE
+APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil.lib"
+!ENDIF
+
+########
+# Support for zlib integration
+!IF "$(ZLIB_SRC)" == ""
+!ERROR ZLib is required. Please define ZLIB_SRC.
+!ELSE
+ZLIB_FLAGS = /I "$(ZLIB_SRC)"
+!IF "$(ZLIB_DLL)" == ""
+!IF "$(ZLIB_LIBDIR)" == ""
+!IF "$(DEBUG_BUILD)" == ""
+ZLIB_LIBS = "$(ZLIB_SRC)\zlibstat.lib"
+!ELSE
+ZLIB_LIBS = "$(ZLIB_SRC)\zlibstatD.lib"
+!ENDIF
+!ELSE
+ZLIB_LIBS = "$(ZLIB_LIBDIR)\x86\ZlibStat$(INTDIR)\zlibstat.lib"
+ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_WINAPI
+!ENDIF
+!ELSE
+ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_DLL
+ZLIB_LIBS = "$(ZLIB_SRC)\zlibdll.lib"
+!ENDIF
+!ENDIF
+
+
+# Exclude stuff we don't need from the Win32 headers
+WIN32_DEFS = /D WIN32 /D WIN32_LEAN_AND_MEAN /D NOUSER /D NOGDI /D NONLS /D NOCRYPT
+
+CPP=cl.exe
+CPP_PROJ = /c /nologo $(CFLAGS) $(WIN32_DEFS) $(EXPAT_FLAGS) $(APR_FLAGS) $(APRUTIL_FLAGS) $(OPENSSL_FLAGS) $(ZLIB_FLAGS) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"
+LIB32=link.exe
+LIB32_FLAGS=/nologo
+
+LIB32_OBJS= \
+ "$(INTDIR)\aggregate_buckets.obj" \
+ "$(INTDIR)\context.obj" \
+ "$(INTDIR)\allocator.obj" \
+ "$(INTDIR)\barrier_buckets.obj" \
+ "$(INTDIR)\buckets.obj" \
+ "$(INTDIR)\chunk_buckets.obj" \
+ "$(INTDIR)\dechunk_buckets.obj" \
+ "$(INTDIR)\deflate_buckets.obj" \
+ "$(INTDIR)\file_buckets.obj" \
+ "$(INTDIR)\headers_buckets.obj" \
+ "$(INTDIR)\limit_buckets.obj" \
+ "$(INTDIR)\mmap_buckets.obj" \
+ "$(INTDIR)\request_buckets.obj" \
+ "$(INTDIR)\response_buckets.obj" \
+ "$(INTDIR)\simple_buckets.obj" \
+ "$(INTDIR)\socket_buckets.obj" \
+ "$(INTDIR)\ssl_buckets.obj" \
+
+!IFDEF OPENSSL_STATIC
+LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32\libeay32.lib" \
+ "$(OPENSSL_SRC)\out32\ssleay32.lib"
+!ELSE
+LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32dll\libeay32.lib" \
+ "$(OPENSSL_SRC)\out32dll\ssleay32.lib"
+!ENDIF
+
+LIB32_OBJS = $(LIB32_OBJS) $(APR_LIBS) $(APRUTIL_LIBS) $(ZLIB_LIBS)
+
+TEST_OBJS = \
+ "$(INTDIR)\CuTest.obj" \
+ "$(INTDIR)\test_all.obj" \
+ "$(INTDIR)\test_util.obj" \
+ "$(INTDIR)\test_context.obj" \
+ "$(INTDIR)\test_buckets.obj" \
+ "$(INTDIR)\test_ssl.obj" \
+
+ALL: INTDIR $(STATIC_LIB) TESTS
+
+CLEAN:
+ -@erase /q "$(INTDIR)" >nul
+
+INTDIR:
+ -@if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+TESTS: $(STATIC_LIB) $(INTDIR)\serf_response.exe $(INTDIR)\serf_get.exe \
+ $(INTDIR)\serf_request.exe $(INTDIR)\test_all.exe
+
+CHECK: INTDIR TESTS
+ $(INTDIR)\serf_response.exe test\testcases\simple.response
+ $(INTDIR)\serf_response.exe test\testcases\chunked-empty.response
+ $(INTDIR)\serf_response.exe test\testcases\chunked.response
+ $(INTDIR)\serf_response.exe test\testcases\chunked-trailers.response
+ $(INTDIR)\serf_response.exe test\testcases\deflate.response
+ $(INTDIR)\test_all.exe
+
+"$(STATIC_LIB)": INTDIR $(LIB32_OBJS)
+ $(LIB32) -lib @<<
+ $(LIB32_FLAGS) $(LIB32_OBJS) /OUT:$@
+<<
+
+
+.c{$(INTDIR)}.obj:
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+{buckets}.c{$(INTDIR)}.obj:
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+{test}.c{$(INTDIR)}.obj:
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+$(INTDIR)\serf_response.exe: $(INTDIR)\serf_response.obj $(STATIC_LIB)
+ $(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS)
+
+$(INTDIR)\serf_get.exe: $(INTDIR)\serf_get.obj $(STATIC_LIB)
+ $(LIB32) /OUT:$@ $** $(LIB32_FLAGS)
+
+$(INTDIR)\serf_request.exe: $(INTDIR)\serf_request.obj $(STATIC_LIB)
+ $(LIB32) /OUT:$@ $** $(LIB32_FLAGS)
+
+$(INTDIR)\test_all.exe: $(TEST_OBJS) $(STATIC_LIB)
+ $(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS)
#define SERF_BUCKET_TYPES_H
#include <apr_mmap.h>
+#include <apr_hash.h>
/* this header and serf.h refer to each other, so take a little extra care */
#ifndef SERF_H
const char *uri,
serf_bucket_t *body);
+/**
+ * Sets the root url of the remote host. If this request contains a relative
+ * url, it will be prefixed with the root url to form an absolute url.
+ * @a bucket is the request bucket. @a root_url is the absolute url of the
+ * root of the remote host, without the closing '/'.
+ */
+SERF_DECLARE(void) serf_bucket_request_set_root(serf_bucket_t *bucket,
+ const char *root_url);
+
/* ==================================================================== */
apr_socket_t *skt,
serf_bucket_alloc_t *allocator);
+/**
+ * Call @a progress_func every time bytes are read from the socket, pass
+ * the number of bytes read.
+ *
+ * When using serf's bytes read & written progress indicator, pass
+ * @a serf_context_progress_delta for progress_func and the serf_context for
+ * progress_baton.
+ */
+SERF_DECLARE(void) serf_bucket_socket_set_read_progress_cb(
+ serf_bucket_t *bucket,
+ const serf_progress_t progress_func,
+ void *progress_baton);
/* ==================================================================== */
* Set the specified @a header and @a value into the bucket, without
* copying either attribute. Both attributes should remain in scope at
* least as long as the bucket.
+ *
+ * @note In the case where a header already exists this will result
+ * in a reallocation and copy, @see serf_bucket_headers_setn.
*/
SERF_DECLARE(void) serf_bucket_headers_setn(
serf_bucket_t *headers_bucket,
* be copied if @a header_copy is set, and the value is copied if
* @a value_copy is set. If the values are not copied, then they should
* remain in scope at least as long as the bucket.
+ *
+ * If @a headers_bucket already contains a header with the same name
+ * as @a header, then append @a value to the existing value,
+ * separating with a comma (as per RFC 2616, section 4.2). In this
+ * case, the new value must be allocated and the header re-used, so
+ * behave as if @a value_copy were true and @a header_copy false.
*/
SERF_DECLARE(void) serf_bucket_headers_setx(
serf_bucket_t *headers_bucket,
*/
typedef int (serf_bucket_headers_do_callback_fn_t)(
void *baton,
- const char *key,
+ const char *key,
const char *value);
/**
/* ==================================================================== */
-
+#define SERF_SSL_CERT_NOTYETVALID 1
+#define SERF_SSL_CERT_EXPIRED 2
+#define SERF_SSL_CERT_UNKNOWNCA 4
+#define SERF_SSL_CERT_SELF_SIGNED 8
+#define SERF_SSL_CERT_UNKNOWN_FAILURE 16
SERF_DECLARE_DATA extern const serf_bucket_type_t serf_bucket_type_ssl_encrypt;
#define SERF_BUCKET_IS_SSL_ENCRYPT(b) SERF_BUCKET_CHECK((b), ssl_encrypt)
typedef struct serf_ssl_context_t serf_ssl_context_t;
+typedef struct serf_ssl_certificate_t serf_ssl_certificate_t;
typedef apr_status_t (*serf_ssl_need_client_cert_t)(void *data,
const char **cert_path);
const char *cert_path,
const char **password);
+typedef apr_status_t
+(*serf_ssl_need_server_cert_t)(void *data,
+ int failures,
+ const serf_ssl_certificate_t *cert);
+
SERF_DECLARE(void)
serf_ssl_client_cert_provider_set(serf_ssl_context_t *context,
serf_ssl_need_client_cert_t callback,
serf_ssl_need_cert_password_t callback,
void *data,
void *cache_pool);
+/**
+ * Set a callback to override the default SSL server certificate validation
+ * algorithm.
+ */
+SERF_DECLARE(void)
+serf_ssl_server_cert_callback_set(serf_ssl_context_t *context,
+ serf_ssl_need_server_cert_t callback,
+ void *data);
+
+/**
+ * Use the default root CA certificates as included with the OpenSSL library.
+ */
+SERF_DECLARE(apr_status_t)
+serf_ssl_use_default_certificates(serf_ssl_context_t *context);
+
+/**
+ * Extract the fields of the issuer in a table with keys (E, CN, OU, O, L,
+ * ST and C). The returned table will be allocated in @a pool.
+ */
+SERF_DECLARE(apr_hash_t *)
+serf_ssl_cert_issuer(const serf_ssl_certificate_t *cert, apr_pool_t *pool);
+
+/**
+ * Extract the fields of the subject in a table with keys (E, CN, OU, O, L,
+ * ST and C). The returned table will be allocated in @a pool.
+ */
+SERF_DECLARE(apr_hash_t *)
+serf_ssl_cert_subject(const serf_ssl_certificate_t *cert, apr_pool_t *pool);
+
+/**
+ * Extract the fields of the certificate in a table with keys (sha1, notBefore,
+ * notAfter). The returned table will be allocated in @a pool.
+ */
+SERF_DECLARE(apr_hash_t *)
+serf_ssl_cert_certificate(const serf_ssl_certificate_t *cert, apr_pool_t *pool);
+
+/**
+ * Load a CA certificate file from a path @a file_path. If the file was loaded
+ * and parsed correctly, a certificate @a cert will be created and returned.
+ * This certificate object will be alloced in @a pool.
+ */
+SERF_DECLARE(apr_status_t)
+serf_ssl_load_cert_file(serf_ssl_certificate_t **cert, const char *file_path,
+ apr_pool_t *pool);
+
+/**
+ * Adds the certificate @a cert to the list of trusted certificates in
+ * @a ssl_ctx that will be used for verification.
+ * See also @a serf_ssl_load_cert_file.
+ */
+SERF_DECLARE(apr_status_t)
+serf_ssl_trust_cert(serf_ssl_context_t *ssl_ctx, serf_ssl_certificate_t *cert);
SERF_DECLARE(serf_bucket_t *) serf_bucket_ssl_encrypt_create(
serf_bucket_t *stream,
-#!/usr/bin/python
+#!/usr/bin/env python
import os
import re
('buckets', 'chunk_buckets'),
]
+TEST_DEPS = [
+ ('test', 'CuTest'),
+ ('test', 'test_util'),
+ ('test', 'test_context'),
+ ('test', 'test_buckets'),
+ ('test', 'test_ssl'),
+ ]
+
+TEST_HDR_FILES = [
+ ('test', 'CuTest'),
+ ('test', 'test_serf'),
+ ]
+
TEST_FILES = [
('test', 'serf_get'),
('test', 'serf_response'),
('test', 'serf_request'),
('test', 'serf_spider'),
+ ('test', 'test_all'),
]
TESTCASES = [
def cmd_check(param):
builder = Builder(param)
- builder.build_target(File('test', 'serf_response', None), False)
+ for dirpath, fname in TEST_FILES:
+ builder.build_target(File(dirpath, fname, None), False)
for dirpath, fname in TESTCASES:
case = os.path.join(dirpath, fname)
print '== Testing %s ==' % case
result = os.system('%s %s' % (os.path.join('test', 'serf_response'), case))
if result:
- raise TestError(case, result)
+ raise TestError("", result)
+ # run the test suite based on the CuTest framework
+ result = os.system(os.path.join('test', 'test_all'))
+ if result:
+ raise TestError(case, result)
def cmd_clean(param):
clean = [File(dirpath, fname, 'o') for dirpath, fname in LIB_FILES]
clean += [File(dirpath, fname, 'o') for dirpath, fname in TEST_FILES]
clean += [File(dirpath, fname, 'lo') for dirpath, fname in TEST_FILES]
clean += [File(dirpath, fname, None) for dirpath, fname in TEST_FILES]
+ clean += [File(dirpath, fname, 'o') for dirpath, fname in TEST_DEPS]
+ clean += [File(dirpath, fname, 'lo') for dirpath, fname in TEST_DEPS]
for i in clean:
if i.mtime:
os.remove(i.fname)
self._add_dep(lib, libobjs, cmd)
# load the test program dependencies now
+ testhdrs = hdrs
+ testhdrs += [File(dirpath, fname, 'h') for dirpath, fname in TEST_HDR_FILES]
+ testdeps = [File(dirpath, fname, 'c') for dirpath, fname in TEST_DEPS]
+ testobjs = [File(dirpath, fname, 'lo') for dirpath, fname in TEST_DEPS]
+
+ for testsrc, testobj in zip(testdeps, testobjs):
+ self._add_compile(testsrc, testobj, testhdrs)
+
for dirpath, fname in TEST_FILES:
src = File(dirpath, fname, 'c')
obj = File(dirpath, fname, 'lo')
self._add_compile(src, obj, hdrs)
- cmd = '%s --silent --mode=link %s %s -static -o %s %s %s %s' % (
- self.LIBTOOL, self.CC, self.LDFLAGS,
- prog.fname, lib.fname, obj.fname, self.LIBS)
- self._add_dep(prog, [lib, obj], cmd)
+ # test_all requires extra dependencies
+ if fname == "test_all":
+ cmd = '%s --silent --mode=link %s %s -static -o %s %s %s %s' % (
+ self.LIBTOOL, self.CC, self.LDFLAGS,
+ prog.fname, lib.fname, ' '.join([l.fname for l in [obj] + testobjs]),
+ self.LIBS)
+ self._add_dep(prog, [lib, obj] + testobjs, cmd)
+ else:
+ cmd = '%s --silent --mode=link %s %s -static -o %s %s %s %s' % (
+ self.LIBTOOL, self.CC, self.LDFLAGS,
+ prog.fname, lib.fname, obj.fname, self.LIBS)
+ self._add_dep(prog, [lib, obj], cmd)
def _add_compile(self, src, obj, hdrs):
cmd = '%s --silent --mode=compile %s %s %s %s -c -o %s %s' % (
--- /dev/null
+Originally obtained from "http://cutest.sourceforge.net/" version 1.4.
+
+HOW TO USE
+
+You can use CuTest to create unit tests to drive your development
+in the style of Extreme Programming. You can also add unit tests to
+existing code to ensure that it works as you suspect.
+
+Your unit tests are an investment. They let you to change your
+code and add new features confidently without worrying about
+accidentally breaking earlier features.
+
+
+LICENSING
+
+Copyright (c) 2003 Asim Jalis
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in
+a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+
+GETTING STARTED
+
+To add unit testing to your C code the only files you need are
+CuTest.c and CuTest.h.
+
+CuTestTest.c and AllTests.c have been included to provide an
+example of how to write unit tests and then how to aggregate them
+into suites and into a single AllTests.c file. Suites allow you
+to put group tests into logical sets. AllTests.c combines all the
+suites and runs them.
+
+You should not have to look inside CuTest.c. Looking in
+CuTestTest.c and AllTests.c (for example usage) should be
+sufficient.
+
+After downloading the sources, run your compiler to create an
+executable called AllTests.exe. For example, if you are using
+Windows with the cl.exe compiler you would type:
+
+ cl.exe AllTests.c CuTest.c CuTestTest.c
+ AllTests.exe
+
+This will run all the unit tests associated with CuTest and print
+the output on the console. You can replace cl.exe with gcc or
+your favorite compiler in the command above.
+
+
+DETAILED EXAMPLE
+
+Here is a more detailed example. We will work through a simple
+test first exercise. The goal is to create a library of string
+utilities. First, lets write a function that converts a
+null-terminated string to all upper case.
+
+Ensure that CuTest.c and CuTest.h are accessible from your C
+project. Next, create a file called StrUtil.c with these
+contents:
+
+ #include "CuTest.h"
+
+ char* StrToUpper(char* str) {
+ return str;
+ }
+
+ void TestStrToUpper(CuTest *tc) {
+ char* input = strdup("hello world");
+ char* actual = StrToUpper(input);
+ char* expected = "HELLO WORLD";
+ CuAssertStrEquals(tc, expected, actual);
+ }
+
+ CuSuite* StrUtilGetSuite() {
+ CuSuite* suite = CuSuiteNew();
+ SUITE_ADD_TEST(suite, TestStrToUpper);
+ return suite;
+ }
+
+Create another file called AllTests.c with these contents:
+
+ #include "CuTest.h"
+
+ CuSuite* StrUtilGetSuite();
+
+ void RunAllTests(void) {
+ CuString *output = CuStringNew();
+ CuSuite* suite = CuSuiteNew();
+
+ CuSuiteAddSuite(suite, StrUtilGetSuite());
+
+ CuSuiteRun(suite);
+ CuSuiteSummary(suite, output);
+ CuSuiteDetails(suite, output);
+ printf("%s\n", output->buffer);
+ }
+
+ int main(void) {
+ RunAllTests();
+ }
+
+Then type this on the command line:
+
+ gcc AllTests.c CuTest.c StrUtil.c
+
+to compile. You can replace gcc with your favorite compiler.
+CuTest should be portable enough to handle all Windows and Unix
+compilers. Then to run the tests type:
+
+ a.out
+
+This will print an error because we haven't implemented the
+StrToUpper function correctly. We are just returning the string
+without changing it to upper case.
+
+ char* StrToUpper(char* str) {
+ return str;
+ }
+
+Rewrite this as follows:
+
+ char* StrToUpper(char* str) {
+ char* p;
+ for (p = str ; *p ; ++p) *p = toupper(*p);
+ return str;
+ }
+
+Recompile and run the tests again. The test should pass this
+time.
+
+
+WHAT TO DO NEXT
+
+At this point you might want to write more tests for the
+StrToUpper function. Here are some ideas:
+
+TestStrToUpper_EmptyString : pass in ""
+TestStrToUpper_UpperCase : pass in "HELLO WORLD"
+TestStrToUpper_MixedCase : pass in "HELLO world"
+TestStrToUpper_Numbers : pass in "1234 hello"
+
+As you write each one of these tests add it to StrUtilGetSuite
+function. If you don't the tests won't be run. Later as you write
+other functions and write tests for them be sure to include those
+in StrUtilGetSuite also. The StrUtilGetSuite function should
+include all the tests in StrUtil.c
+
+Over time you will create another file called FunkyStuff.c
+containing other functions unrelated to StrUtil. Follow the same
+pattern. Create a FunkyStuffGetSuite function in FunkyStuff.c.
+And add FunkyStuffGetSuite to AllTests.c.
+
+The framework is designed in the way it is so that it is easy to
+organize a lot of tests.
+
+THE BIG PICTURE
+
+Each individual test corresponds to a CuTest. These are grouped
+to form a CuSuite. CuSuites can hold CuTests or other CuSuites.
+AllTests.c collects all the CuSuites in the program into a single
+CuSuite which it then runs as a single CuSuite.
+
+The project is open source so feel free to take a peek under the
+hood at the CuTest.c file to see how it works. CuTestTest.c
+contains tests for CuTest.c. So CuTest tests itself.
+
+Since AllTests.c has a main() you will need to exclude this when
+you are building your product. Here is a nicer way to do this if
+you want to avoid messing with multiple builds. Remove the main()
+in AllTests.c. Note that it just calls RunAllTests(). Instead
+we'll call this directly from the main program.
+
+Now in the main() of the actual program check to see if the
+command line option "--test" was passed. If it was then I call
+RunAllTests() from AllTests.c. Otherwise run the real program.
+
+Shipping the tests with the code can be useful. If you customers
+complain about a problem you can ask them to run the unit tests
+and send you the output. This can help you to quickly isolate the
+piece of your system that is malfunctioning in the customer's
+environment.
+
+CuTest offers a rich set of CuAssert functions. Here is a list:
+
+void CuAssert(CuTest* tc, char* message, int condition);
+void CuAssertTrue(CuTest* tc, int condition);
+void CuAssertStrEquals(CuTest* tc, char* expected, char* actual);
+void CuAssertIntEquals(CuTest* tc, int expected, int actual);
+void CuAssertPtrEquals(CuTest* tc, void* expected, void* actual);
+void CuAssertPtrNotNull(CuTest* tc, void* pointer);
+
+The project is open source and so you can add other more powerful
+asserts to make your tests easier to write and more concise.
+Please feel free to send me changes you make so that I can
+incorporate them into future releases.
+
+If you see any errors in this document please contact me at
+asimjalis@peakprogramming.com.
+
+
+AUTOMATING TEST SUITE GENERATION
+
+make-tests.sh will grep through all the .c files in the current
+directory and generate the code to run all the tests contained in
+them. Using this script you don't have to worry about writing
+AllTests.c or dealing with any of the other suite code.
+
+
+CREDITS
+
+[02.23.2003] Dave Glowacki <dglo@hyde.ssec.wisc.edu> has added
+(1) file name and line numbers to the error messages, (2)
+AssertDblEquals for doubles, (3) Assert<X>Equals_Msg version of
+all the Assert<X>Equals to pass in optional message which is
+printed out on assert failure.
--- /dev/null
+/*
+ * Copyright (c) 2003 Asim Jalis
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose, including commercial applications, and to alter it and
+ * redistribute it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you
+ * must not claim that you wrote the original software. If you use
+ * this software in a product, an acknowledgment in the product
+ * documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and
+ * must not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *-------------------------------------------------------------------------*
+ *
+ * Originally obtained from "http://cutest.sourceforge.net/" version 1.4.
+ *
+ * Modified for serf as follows
+ * 1) added CuStringFree(), CuTestFree(), CuSuiteFree(), and
+ * CuSuiteFreeDeep()
+ * 0) reformatted the whitespace (doh!)
+ */
+#include <assert.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "CuTest.h"
+
+/*-------------------------------------------------------------------------*
+ * CuStr
+ *-------------------------------------------------------------------------*/
+
+char* CuStrAlloc(int size)
+{
+ char* newStr = (char*) malloc( sizeof(char) * (size) );
+ return newStr;
+}
+
+char* CuStrCopy(const char* old)
+{
+ int len = strlen(old);
+ char* newStr = CuStrAlloc(len + 1);
+ strcpy(newStr, old);
+ return newStr;
+}
+
+/*-------------------------------------------------------------------------*
+ * CuString
+ *-------------------------------------------------------------------------*/
+
+void CuStringInit(CuString* str)
+{
+ str->length = 0;
+ str->size = STRING_MAX;
+ str->buffer = (char*) malloc(sizeof(char) * str->size);
+ str->buffer[0] = '\0';
+}
+
+CuString* CuStringNew(void)
+{
+ CuString* str = (CuString*) malloc(sizeof(CuString));
+ str->length = 0;
+ str->size = STRING_MAX;
+ str->buffer = (char*) malloc(sizeof(char) * str->size);
+ str->buffer[0] = '\0';
+ return str;
+}
+
+void CuStringFree(CuString *str)
+{
+ free(str->buffer);
+ free(str);
+}
+
+void CuStringResize(CuString* str, int newSize)
+{
+ str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize);
+ str->size = newSize;
+}
+
+void CuStringAppend(CuString* str, const char* text)
+{
+ int length;
+
+ if (text == NULL) {
+ text = "NULL";
+ }
+
+ length = strlen(text);
+ if (str->length + length + 1 >= str->size)
+ CuStringResize(str, str->length + length + 1 + STRING_INC);
+ str->length += length;
+ strcat(str->buffer, text);
+}
+
+void CuStringAppendChar(CuString* str, char ch)
+{
+ char text[2];
+ text[0] = ch;
+ text[1] = '\0';
+ CuStringAppend(str, text);
+}
+
+void CuStringAppendFormat(CuString* str, const char* format, ...)
+{
+ va_list argp;
+ char buf[HUGE_STRING_LEN];
+ va_start(argp, format);
+ vsprintf(buf, format, argp);
+ va_end(argp);
+ CuStringAppend(str, buf);
+}
+
+void CuStringInsert(CuString* str, const char* text, int pos)
+{
+ int length = strlen(text);
+ if (pos > str->length)
+ pos = str->length;
+ if (str->length + length + 1 >= str->size)
+ CuStringResize(str, str->length + length + 1 + STRING_INC);
+ memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1);
+ str->length += length;
+ memcpy(str->buffer + pos, text, length);
+}
+
+/*-------------------------------------------------------------------------*
+ * CuTest
+ *-------------------------------------------------------------------------*/
+
+void CuTestInit(CuTest* t, const char* name, TestFunction function)
+{
+ t->name = CuStrCopy(name);
+ t->failed = 0;
+ t->ran = 0;
+ t->message = NULL;
+ t->function = function;
+ t->jumpBuf = NULL;
+}
+
+CuTest* CuTestNew(const char* name, TestFunction function)
+{
+ CuTest* tc = CU_ALLOC(CuTest);
+ CuTestInit(tc, name, function);
+ return tc;
+}
+
+void CuTestFree(CuTest* tc)
+{
+ free(tc->name);
+ free(tc);
+}
+
+void CuTestRun(CuTest* tc)
+{
+ jmp_buf buf;
+ tc->jumpBuf = &buf;
+ if (setjmp(buf) == 0)
+ {
+ tc->ran = 1;
+ (tc->function)(tc);
+ }
+ tc->jumpBuf = 0;
+}
+
+static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
+{
+ char buf[HUGE_STRING_LEN];
+
+ sprintf(buf, "%s:%d: ", file, line);
+ CuStringInsert(string, buf, 0);
+
+ tc->failed = 1;
+ tc->message = string->buffer;
+ if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
+}
+
+void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message)
+{
+ CuString string;
+
+ CuStringInit(&string);
+ if (message2 != NULL)
+ {
+ CuStringAppend(&string, message2);
+ CuStringAppend(&string, ": ");
+ }
+ CuStringAppend(&string, message);
+ CuFailInternal(tc, file, line, &string);
+}
+
+void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition)
+{
+ if (condition) return;
+ CuFail_Line(tc, file, line, NULL, message);
+}
+
+void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ const char* expected, const char* actual)
+{
+ CuString string;
+ if ((expected == NULL && actual == NULL) ||
+ (expected != NULL && actual != NULL &&
+ strcmp(expected, actual) == 0))
+ {
+ return;
+ }
+
+ CuStringInit(&string);
+ if (message != NULL)
+ {
+ CuStringAppend(&string, message);
+ CuStringAppend(&string, ": ");
+ }
+ CuStringAppend(&string, "expected <");
+ CuStringAppend(&string, expected);
+ CuStringAppend(&string, "> but was <");
+ CuStringAppend(&string, actual);
+ CuStringAppend(&string, ">");
+ CuFailInternal(tc, file, line, &string);
+}
+
+void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ int expected, int actual)
+{
+ char buf[STRING_MAX];
+ if (expected == actual) return;
+ sprintf(buf, "expected <%d> but was <%d>", expected, actual);
+ CuFail_Line(tc, file, line, message, buf);
+}
+
+void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ double expected, double actual, double delta)
+{
+ char buf[STRING_MAX];
+ if (fabs(expected - actual) <= delta) return;
+ sprintf(buf, "expected <%lf> but was <%lf>", expected, actual);
+ CuFail_Line(tc, file, line, message, buf);
+}
+
+void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
+ void* expected, void* actual)
+{
+ char buf[STRING_MAX];
+ if (expected == actual) return;
+ sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
+ CuFail_Line(tc, file, line, message, buf);
+}
+
+
+/*-------------------------------------------------------------------------*
+ * CuSuite
+ *-------------------------------------------------------------------------*/
+
+void CuSuiteInit(CuSuite* testSuite)
+{
+ testSuite->count = 0;
+ testSuite->failCount = 0;
+}
+
+CuSuite* CuSuiteNew(void)
+{
+ CuSuite* testSuite = CU_ALLOC(CuSuite);
+ CuSuiteInit(testSuite);
+ return testSuite;
+}
+
+void CuSuiteFree(CuSuite *testSuite)
+{
+ free(testSuite);
+}
+
+void CuSuiteFreeDeep(CuSuite *testSuite)
+{
+ int i;
+ for (i = 0 ; i < testSuite->count ; ++i)
+ {
+ CuTest* testCase = testSuite->list[i];
+ CuTestFree(testCase);
+ }
+ free(testSuite);
+}
+
+void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase)
+{
+ assert(testSuite->count < MAX_TEST_CASES);
+ testSuite->list[testSuite->count] = testCase;
+ testSuite->count++;
+}
+
+void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2)
+{
+ int i;
+ for (i = 0 ; i < testSuite2->count ; ++i)
+ {
+ CuTest* testCase = testSuite2->list[i];
+ CuSuiteAdd(testSuite, testCase);
+ }
+}
+
+void CuSuiteRun(CuSuite* testSuite)
+{
+ int i;
+ for (i = 0 ; i < testSuite->count ; ++i)
+ {
+ CuTest* testCase = testSuite->list[i];
+ CuTestRun(testCase);
+ if (testCase->failed) { testSuite->failCount += 1; }
+ }
+}
+
+void CuSuiteSummary(CuSuite* testSuite, CuString* summary)
+{
+ int i;
+ for (i = 0 ; i < testSuite->count ; ++i)
+ {
+ CuTest* testCase = testSuite->list[i];
+ CuStringAppend(summary, testCase->failed ? "F" : ".");
+ }
+ CuStringAppend(summary, "\n\n");
+}
+
+void CuSuiteDetails(CuSuite* testSuite, CuString* details)
+{
+ int i;
+ int failCount = 0;
+
+ if (testSuite->failCount == 0)
+ {
+ int passCount = testSuite->count - testSuite->failCount;
+ const char* testWord = passCount == 1 ? "test" : "tests";
+ CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord);
+ }
+ else
+ {
+ if (testSuite->failCount == 1)
+ CuStringAppend(details, "There was 1 failure:\n");
+ else
+ CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount);
+
+ for (i = 0 ; i < testSuite->count ; ++i)
+ {
+ CuTest* testCase = testSuite->list[i];
+ if (testCase->failed)
+ {
+ failCount++;
+ CuStringAppendFormat(details, "%d) %s: %s\n",
+ failCount, testCase->name, testCase->message);
+ }
+ }
+ CuStringAppend(details, "\n!!!FAILURES!!!\n");
+
+ CuStringAppendFormat(details, "Runs: %d ", testSuite->count);
+ CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount);
+ CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2003 Asim Jalis
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose, including commercial applications, and to alter it and
+ * redistribute it freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you
+ * must not claim that you wrote the original software. If you use
+ * this software in a product, an acknowledgment in the product
+ * documentation would be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and
+ * must not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *-------------------------------------------------------------------------*
+ *
+ * Originally obtained from "http://cutest.sourceforge.net/" version 1.4.
+ *
+ * Modified for serf as follows
+ * 2) removed const from struct CuTest.name
+ * 1) added CuStringFree(), CuTestFree(), CuSuiteFree(), and
+ * CuSuiteFreeDeep()
+ * 0) reformatted the whitespace (doh!)
+ */
+#ifndef CU_TEST_H
+#define CU_TEST_H
+
+#include <setjmp.h>
+#include <stdarg.h>
+
+/* CuString */
+
+char* CuStrAlloc(int size);
+char* CuStrCopy(const char* old);
+
+#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE)))
+
+#define HUGE_STRING_LEN 8192
+#define STRING_MAX 256
+#define STRING_INC 256
+
+typedef struct
+{
+ int length;
+ int size;
+ char* buffer;
+} CuString;
+
+void CuStringInit(CuString* str);
+CuString* CuStringNew(void);
+void CuStringFree(CuString *str);
+void CuStringRead(CuString* str, const char* path);
+void CuStringAppend(CuString* str, const char* text);
+void CuStringAppendChar(CuString* str, char ch);
+void CuStringAppendFormat(CuString* str, const char* format, ...);
+void CuStringInsert(CuString* str, const char* text, int pos);
+void CuStringResize(CuString* str, int newSize);
+
+/* CuTest */
+
+typedef struct CuTest CuTest;
+
+typedef void (*TestFunction)(CuTest *);
+
+struct CuTest
+{
+ char* name;
+ TestFunction function;
+ int failed;
+ int ran;
+ const char* message;
+ jmp_buf *jumpBuf;
+};
+
+void CuTestInit(CuTest* t, const char* name, TestFunction function);
+CuTest* CuTestNew(const char* name, TestFunction function);
+void CuTestFree(CuTest* tc);
+void CuTestRun(CuTest* tc);
+
+/* Internal versions of assert functions -- use the public versions */
+void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message);
+void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition);
+void CuAssertStrEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ const char* expected, const char* actual);
+void CuAssertIntEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ int expected, int actual);
+void CuAssertDblEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ double expected, double actual, double delta);
+void CuAssertPtrEquals_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ void* expected, void* actual);
+
+/* public assert functions */
+
+#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms))
+#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond))
+#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond))
+
+#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
+#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
+#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
+#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
+#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl))
+#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl))
+#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
+#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
+
+#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL))
+#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL))
+
+/* CuSuite */
+
+#define MAX_TEST_CASES 1024
+
+#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST))
+
+typedef struct
+{
+ int count;
+ CuTest* list[MAX_TEST_CASES];
+ int failCount;
+
+} CuSuite;
+
+
+void CuSuiteInit(CuSuite* testSuite);
+CuSuite* CuSuiteNew(void);
+void CuSuiteFree(CuSuite *testSuite);
+void CuSuiteFreeDeep(CuSuite *testSuite);
+void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase);
+void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2);
+void CuSuiteRun(CuSuite* testSuite);
+void CuSuiteSummary(CuSuite* testSuite, CuString* summary);
+void CuSuiteDetails(CuSuite* testSuite, CuString* details);
+
+#endif /* CU_TEST_H */
#include "serf.h"
-#define SERF_VERSION_STRING "0.01"
-
typedef struct {
int using_ssl;
serf_ssl_context_t *ssl_ctx;
static apr_status_t setup_request(serf_request_t *request,
void *setup_baton,
serf_bucket_t **req_bkt,
- serf_response_acceptor_t *acceptor, void **acceptor_baton,
+ serf_response_acceptor_t *acceptor,
+ void **acceptor_baton,
serf_response_handler_t *handler,
void **handler_baton,
apr_pool_t *pool)
return APR_SUCCESS;
}
-void print_usage(apr_pool_t *pool)
+static void print_usage(apr_pool_t *pool)
{
puts("serf_get [options] URL");
puts("-h\tDisplay this help");
#include "serf.h"
-/* ### should this be in the header? */
-#define SERF_VERSION_STRING "0.01"
-
-
static apr_status_t drain_bucket(serf_bucket_t *bucket)
{
apr_status_t status;
#include "serf.h"
-#define SERF_VERSION_STRING "0.01"
-
typedef struct {
const char *resp_file;
serf_bucket_t *bkt;
exit(-1);
}
accept_ctx.resp_file = argv[1];
+ accept_ctx.bkt = NULL;
apr_initialize();
atexit(apr_terminate);
#include "serf.h"
#include "serf_bucket_util.h"
-#define SERF_VERSION_STRING "0.01"
/*#define SERF_VERBOSE*/
#if !APR_HAS_THREADS
apr_thread_cond_t *doc_queue_condvar;
const char *hostinfo;
-
- /* includes: path, query, fragment. */
+
+ /* includes: path, query, fragment. */
char *full_path;
apr_size_t full_path_len;
apr_pool_create(&subpool, pool);
while (1) {
- apr_pool_clear(subpool);
-
doc_path_t *dup;
+ apr_pool_clear(subpool);
+
/* Grab it. */
apr_thread_mutex_lock(ctx->mutex);
/* Sleep. */
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ c2:31:db:41:c9:7b:a9:46
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=BE, ST=Antwerp, O=In Serf we trust, Inc., OU=Test Suite, CN=Serf/emailAddress=serf@example.com, L=Mechelen
+ Validity
+ Not Before: Mar 21 13:18:17 2008 GMT
+ Not After : Mar 21 13:18:17 2011 GMT
+ Subject: C=BE, ST=Antwerp, O=In Serf we trust, Inc., OU=Test Suite, CN=Serf/emailAddress=serf@example.com, L=Mechelen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a1:21:58:60:ea:79:ae:9f:0f:f4:69:b5:af:55:
+ 9a:8b:da:1d:74:80:88:44:42:46:64:59:98:3e:84:
+ e1:70:f7:18:e1:7c:8d:cc:42:27:cd:e6:31:47:51:
+ 66:3d:58:1c:f9:54:26:4f:12:b7:0e:46:a7:27:c1:
+ ca:ac:a7:38:0f:a1:00:fb:a8:20:77:37:14:6a:7b:
+ 65:34:1c:eb:30:fa:0b:9e:57:2c:7a:04:13:50:d4:
+ e2:7c:66:5f:97:45:75:78:47:f5:9e:68:9d:40:b9:
+ 94:d3:78:50:c8:19:10:50:52:fd:2f:b8:a1:75:74:
+ ad:73:95:46:9a:8e:95:b2:3d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 15:BB:2D:8C:63:10:0D:31:01:D1:C6:26:01:27:43:A5:F4:57:6E:ED
+ X509v3 Authority Key Identifier:
+ keyid:15:BB:2D:8C:63:10:0D:31:01:D1:C6:26:01:27:43:A5:F4:57:6E:ED
+ DirName:/C=BE/ST=Antwerp/O=In Serf we trust, Inc./OU=Test Suite/CN=Serf/emailAddress=serf@example.com/L=Mechelen
+ serial:C2:31:DB:41:C9:7B:A9:46
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 59:9c:b0:62:cc:a4:c0:98:68:4b:52:bf:fa:84:ee:b5:65:d5:
+ a7:51:39:77:a0:be:d6:14:b0:7a:64:2f:0d:ee:49:e8:b6:6a:
+ c7:1d:5f:bc:27:4c:25:4b:25:b7:69:5c:07:86:54:69:22:99:
+ d9:1a:5d:dd:38:c9:00:b4:29:89:7d:ce:df:b5:3f:57:05:ee:
+ 5b:0e:a4:f0:bc:7a:4f:1b:ba:84:85:e8:0f:e3:6b:fa:6f:cf:
+ 3f:23:7c:d0:dd:c8:95:91:46:8a:05:84:84:46:cf:e3:c8:fc:
+ 9c:94:c2:dd:15:d4:6e:d1:31:0b:d9:7b:ce:1e:13:72:c9:2e:
+ a9:86
+-----BEGIN CERTIFICATE-----
+MIIDsjCCAxugAwIBAgIJAMIx20HJe6lGMA0GCSqGSIb3DQEBBQUAMIGYMQswCQYD
+VQQGEwJCRTEQMA4GA1UECBMHQW50d2VycDEfMB0GA1UEChMWSW4gU2VyZiB3ZSB0
+cnVzdCwgSW5jLjETMBEGA1UECxMKVGVzdCBTdWl0ZTENMAsGA1UEAxMEU2VyZjEf
+MB0GCSqGSIb3DQEJARYQc2VyZkBleGFtcGxlLmNvbTERMA8GA1UEBxMITWVjaGVs
+ZW4wHhcNMDgwMzIxMTMxODE3WhcNMTEwMzIxMTMxODE3WjCBmDELMAkGA1UEBhMC
+QkUxEDAOBgNVBAgTB0FudHdlcnAxHzAdBgNVBAoTFkluIFNlcmYgd2UgdHJ1c3Qs
+IEluYy4xEzARBgNVBAsTClRlc3QgU3VpdGUxDTALBgNVBAMTBFNlcmYxHzAdBgkq
+hkiG9w0BCQEWEHNlcmZAZXhhbXBsZS5jb20xETAPBgNVBAcTCE1lY2hlbGVuMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChIVhg6nmunw/0abWvVZqL2h10gIhE
+QkZkWZg+hOFw9xjhfI3MQifN5jFHUWY9WBz5VCZPErcORqcnwcqspzgPoQD7qCB3
+NxRqe2U0HOsw+gueVyx6BBNQ1OJ8Zl+XRXV4R/WeaJ1AuZTTeFDIGRBQUv0vuKF1
+dK1zlUaajpWyPQIDAQABo4IBADCB/TAdBgNVHQ4EFgQUFbstjGMQDTEB0cYmASdD
+pfRXbu0wgc0GA1UdIwSBxTCBwoAUFbstjGMQDTEB0cYmASdDpfRXbu2hgZ6kgZsw
+gZgxCzAJBgNVBAYTAkJFMRAwDgYDVQQIEwdBbnR3ZXJwMR8wHQYDVQQKExZJbiBT
+ZXJmIHdlIHRydXN0LCBJbmMuMRMwEQYDVQQLEwpUZXN0IFN1aXRlMQ0wCwYDVQQD
+EwRTZXJmMR8wHQYJKoZIhvcNAQkBFhBzZXJmQGV4YW1wbGUuY29tMREwDwYDVQQH
+EwhNZWNoZWxlboIJAMIx20HJe6lGMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF
+BQADgYEAWZywYsykwJhoS1K/+oTutWXVp1E5d6C+1hSwemQvDe5J6LZqxx1fvCdM
+JUslt2lcB4ZUaSKZ2Rpd3TjJALQpiX3O37U/VwXuWw6k8Lx6Txu6hIXoD+Nr+m/P
+PyN80N3IlZFGigWEhEbP48j8nJTC3RXUbtExC9l7zh4TcskuqYY=
+-----END CERTIFICATE-----
--- /dev/null
+/* Copyright 2002-2007 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.
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "test_serf.h"
+#include <stdlib.h>
+
+/* Top-level pool which can be used by tests. */
+apr_pool_t *test_pool;
+
+static const struct testlist {
+ const char *testname;
+ CuSuite *(*func)(void);
+} tests[] = {
+ {"context", test_context},
+ {"buckets", test_buckets},
+ {"ssl", test_ssl},
+ {"LastTest", NULL}
+};
+
+int main(int argc, char *argv[])
+{
+ CuSuite *alltests = NULL;
+ CuString *output = CuStringNew();
+ int i;
+ int list_provided = 0;
+ int exit_code;
+
+ apr_initialize();
+ atexit(apr_terminate);
+
+ apr_pool_create(&test_pool, NULL);
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-v")) {
+ continue;
+ }
+ if (!strcmp(argv[i], "-l")) {
+ for (i = 0; tests[i].func != NULL; i++) {
+ printf("%s\n", tests[i].testname);
+ }
+ exit(0);
+ }
+ if (argv[i][0] == '-') {
+ fprintf(stderr, "invalid option: `%s'\n", argv[i]);
+ exit(1);
+ }
+ list_provided = 1;
+ }
+
+ alltests = CuSuiteNew();
+ if (!list_provided) {
+ /* add everything */
+ for (i = 0; tests[i].func != NULL; i++) {
+ CuSuite *st = tests[i].func();
+ CuSuiteAddSuite(alltests, st);
+ CuSuiteFree(st);
+ }
+ }
+ else {
+ /* add only the tests listed */
+ for (i = 1; i < argc; i++) {
+ int j;
+ int found = 0;
+
+ if (argv[i][0] == '-') {
+ continue;
+ }
+ for (j = 0; tests[j].func != NULL; j++) {
+ if (!strcmp(argv[i], tests[j].testname)) {
+ CuSuiteAddSuite(alltests, tests[j].func());
+ found = 1;
+ }
+ }
+ if (!found) {
+ fprintf(stderr, "invalid test name: `%s'\n", argv[i]);
+ exit(1);
+ }
+ }
+ }
+
+ CuSuiteRun(alltests);
+ CuSuiteSummary(alltests, output);
+ CuSuiteDetails(alltests, output);
+ printf("%s\n", output->buffer);
+
+ exit_code = alltests->failCount > 0 ? 1 : 0;
+
+ CuSuiteFreeDeep(alltests);
+ CuStringFree(output);
+
+ apr_pool_destroy(test_pool);
+
+ return exit_code;
+}
--- /dev/null
+/* Copyright 2002-2007 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.
+ */
+
+#include <apr.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+
+#include "serf.h"
+#include "test_serf.h"
+
+#define CRLF "\r\n"
+
+static void test_simple_bucket_readline(CuTest *tc)
+{
+ serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL,
+ NULL);
+ apr_status_t status;
+ serf_bucket_t *bkt;
+ const char *data;
+ int found;
+ apr_size_t len;
+
+ bkt = SERF_BUCKET_SIMPLE_STRING(
+ "line1" CRLF
+ "line2",
+ alloc);
+
+ /* Initialize parameters to check that they will be initialized. */
+ len = 0x112233;
+ data = 0;
+ status = serf_bucket_readline(bkt, SERF_NEWLINE_CRLF, &found, &data, &len);
+
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+ CuAssertIntEquals(tc, SERF_NEWLINE_CRLF, found);
+ CuAssertIntEquals(tc, 7, len);
+ CuAssert(tc, data, strncmp("line1" CRLF, data, len) == 0);
+
+ /* Initialize parameters to check that they will be initialized. */
+ len = 0x112233;
+ data = 0;
+ status = serf_bucket_readline(bkt, SERF_NEWLINE_CRLF, &found, &data, &len);
+
+ CuAssertIntEquals(tc, APR_EOF, status);
+ CuAssertIntEquals(tc, SERF_NEWLINE_NONE, found);
+ CuAssertIntEquals(tc, 5, len);
+ CuAssert(tc, data, strncmp("line2", data, len) == 0);
+}
+
+/* Reads bucket until EOF found and compares read data with zero terminated
+ string expected. Report all failures using CuTest. */
+static void read_and_check_bucket(CuTest *tc, serf_bucket_t *bkt,
+ const char *expected)
+{
+ apr_status_t status;
+ do
+ {
+ const char *data;
+ apr_size_t len;
+
+ status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len);
+ CuAssert(tc, "Got error during bucket reading.",
+ !SERF_BUCKET_READ_ERROR(status));
+ CuAssert(tc, "Read more data than expected.",
+ strlen(expected) >= len);
+ CuAssert(tc, "Read data is not equal to expected.",
+ strncmp(expected, data, len) == 0);
+
+ expected += len;
+ } while(!APR_STATUS_IS_EOF(status));
+
+ CuAssert(tc, "Read less data than expected.", strlen(expected) == 0);
+}
+
+static void test_response_bucket_read(CuTest *tc)
+{
+ serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL,
+ NULL);
+ serf_bucket_t *bkt, *tmp;
+
+ tmp = SERF_BUCKET_SIMPLE_STRING(
+ "HTTP/1.1 200 OK" CRLF
+ "Content-Length: 7" CRLF
+ CRLF
+ "abc1234",
+ alloc);
+
+ bkt = serf_bucket_response_create(tmp, alloc);
+
+ /* Read all bucket and check it content. */
+ read_and_check_bucket(tc, bkt, "abc1234");
+}
+
+static void test_response_bucket_chunked_read(CuTest *tc)
+{
+ serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL,
+ NULL);
+ serf_bucket_t *bkt, *tmp, *hdrs;
+
+ tmp = SERF_BUCKET_SIMPLE_STRING(
+ "HTTP/1.1 200 OK" CRLF
+ "Transfer-Encoding: chunked" CRLF
+ CRLF
+ "3" CRLF
+ "abc" CRLF
+ "4" CRLF
+ "1234" CRLF
+ "0" CRLF
+ "Footer: value" CRLF
+ CRLF,
+ alloc);
+
+ bkt = serf_bucket_response_create(tmp, alloc);
+
+ /* Read all bucket and check it content. */
+ read_and_check_bucket(tc, bkt, "abc1234");
+
+ hdrs = serf_bucket_response_get_headers(bkt);
+ CuAssertTrue(tc, hdrs != NULL);
+
+ /* Check that trailing headers parsed correctly. */
+ CuAssertStrEquals(tc, "value", serf_bucket_headers_get(hdrs, "Footer"));
+}
+
+static void test_bucket_header_set(CuTest *tc)
+{
+ serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL,
+ NULL);
+ serf_bucket_t *hdrs = serf_bucket_headers_create(alloc);
+
+ CuAssertTrue(tc, hdrs != NULL);
+
+ serf_bucket_headers_set(hdrs, "Foo", "bar");
+
+ CuAssertStrEquals(tc, "bar", serf_bucket_headers_get(hdrs, "Foo"));
+
+ serf_bucket_headers_set(hdrs, "Foo", "baz");
+
+ CuAssertStrEquals(tc, "bar,baz", serf_bucket_headers_get(hdrs, "Foo"));
+}
+
+CuSuite *test_buckets(void)
+{
+ CuSuite *suite = CuSuiteNew();
+
+ SUITE_ADD_TEST(suite, test_simple_bucket_readline);
+ SUITE_ADD_TEST(suite, test_response_bucket_read);
+ SUITE_ADD_TEST(suite, test_response_bucket_chunked_read);
+ SUITE_ADD_TEST(suite, test_bucket_header_set);
+
+ return suite;
+}
--- /dev/null
+/* Copyright 2002-2007 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.
+ */
+
+#include <stdlib.h>
+
+#include <apr.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <apr_version.h>
+
+#include "serf.h"
+
+#include "test_serf.h"
+
+typedef struct {
+ serf_response_acceptor_t acceptor;
+ void *acceptor_baton;
+
+ serf_response_handler_t handler;
+
+ apr_array_header_t *sent_requests;
+ apr_array_header_t *accepted_requests;
+ apr_array_header_t *handled_requests;
+ int req_id;
+
+ const char *method;
+ const char *path;
+ int done;
+
+ const char *server_root;
+ int use_proxy;
+
+ test_baton_t *tb;
+} handler_baton_t;
+
+static serf_bucket_t* accept_response(serf_request_t *request,
+ serf_bucket_t *stream,
+ void *acceptor_baton,
+ apr_pool_t *pool)
+{
+ serf_bucket_t *c;
+ serf_bucket_alloc_t *bkt_alloc;
+ handler_baton_t *ctx = acceptor_baton;
+
+ /* get the per-request bucket allocator */
+ bkt_alloc = serf_request_get_alloc(request);
+
+ /* Create a barrier so the response doesn't eat us! */
+ c = serf_bucket_barrier_create(stream, bkt_alloc);
+
+ APR_ARRAY_PUSH(ctx->accepted_requests, int) = ctx->req_id;
+
+ return serf_bucket_response_create(c, bkt_alloc);
+}
+
+static apr_status_t setup_request(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)
+{
+ handler_baton_t *ctx = setup_baton;
+ serf_bucket_t *body_bkt;
+
+ /* create a simple body text */
+ const char *str = apr_psprintf(pool, "%d", ctx->req_id);
+ body_bkt = serf_bucket_simple_create(str, strlen(str), NULL, NULL,
+ serf_request_get_alloc(request));
+ *req_bkt =
+ serf_request_bucket_request_create(request,
+ ctx->method, ctx->path,
+ body_bkt,
+ serf_request_get_alloc(request));
+
+ APR_ARRAY_PUSH(ctx->sent_requests, int) = ctx->req_id;
+
+ *acceptor = ctx->acceptor;
+ *acceptor_baton = ctx;
+ *handler = ctx->handler;
+ *handler_baton = ctx;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t handle_response(serf_request_t *request,
+ serf_bucket_t *response,
+ void *handler_baton,
+ apr_pool_t *pool)
+{
+ handler_baton_t *ctx = handler_baton;
+
+ if (! response) {
+ serf_connection_request_create(ctx->tb->connection,
+ setup_request,
+ ctx);
+ return APR_SUCCESS;
+ }
+
+ while (1) {
+ apr_status_t status;
+ const char *data;
+ apr_size_t len;
+
+ status = serf_bucket_read(response, 2048, &data, &len);
+ if (SERF_BUCKET_READ_ERROR(status))
+ return status;
+
+ if (APR_STATUS_IS_EOF(status)) {
+ APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id;
+ ctx->done = TRUE;
+ return APR_EOF;
+ }
+
+ }
+
+ return APR_SUCCESS;
+}
+
+/* Validate that requests are sent and completed in the order of creation. */
+static void test_serf_connection_request_create(CuTest *tc)
+{
+ test_baton_t *tb;
+ serf_request_t *request1, *request2;
+ handler_baton_t handler_ctx, handler2_ctx;
+ apr_status_t status;
+ apr_pool_t *iter_pool;
+ apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
+ int i;
+ test_server_action_t action_list[] = {
+ {SERVER_RECV,
+ "GET / HTTP/1.1" CRLF
+ "Transfer-Encoding: chunked" CRLF
+ CRLF
+ "1" CRLF
+ "1" CRLF
+ "0" CRLF
+ CRLF
+ "GET / HTTP/1.1" CRLF
+ "Transfer-Encoding: chunked" CRLF
+ "" CRLF
+ "1" CRLF
+ "2" CRLF
+ "0" CRLF
+ CRLF
+ },
+ {SERVER_SEND,
+ "HTTP/1.1 200 OK" CRLF
+ "Transfer-Encoding: chunked" CRLF
+ CRLF
+ "0" CRLF
+ CRLF
+ "HTTP/1.1 200 OK" CRLF
+ "Transfer-Encoding: chunked" CRLF
+ CRLF
+ "0" CRLF
+ CRLF
+ }
+ };
+
+ accepted_requests = apr_array_make(test_pool, 2, sizeof(int));
+ sent_requests = apr_array_make(test_pool, 2, sizeof(int));
+ handled_requests = apr_array_make(test_pool, 2, sizeof(int));
+
+ /* Set up a test context with a server */
+ status = test_server_create(&tb, action_list, 2, 0, NULL, NULL, NULL,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ handler_ctx.method = "GET";
+ handler_ctx.path = "/";
+ handler_ctx.done = FALSE;
+
+ handler_ctx.acceptor = accept_response;
+ handler_ctx.acceptor_baton = NULL;
+ handler_ctx.handler = handle_response;
+ handler_ctx.req_id = 1;
+ handler_ctx.accepted_requests = accepted_requests;
+ handler_ctx.sent_requests = sent_requests;
+ handler_ctx.handled_requests = handled_requests;
+ handler_ctx.use_proxy = FALSE;
+ handler_ctx.server_root = NULL;
+
+ request1 = serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler_ctx);
+
+ handler2_ctx = handler_ctx;
+ handler2_ctx.req_id = 2;
+
+ request2 = serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler2_ctx);
+
+ apr_pool_create(&iter_pool, test_pool);
+
+ while (!handler_ctx.done && !handler2_ctx.done)
+ {
+ apr_pool_clear(iter_pool);
+
+ status = test_server_run(tb, 0, iter_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = serf_context_run(tb->context, 0, iter_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Debugging purposes only! */
+ serf_debug__closed_conn(tb->bkt_alloc);
+ }
+ apr_pool_destroy(iter_pool);
+
+ /* Check that all requests were received */
+ CuAssertIntEquals(tc, 2, sent_requests->nelts);
+ CuAssertIntEquals(tc, 2, accepted_requests->nelts);
+ CuAssertIntEquals(tc, 2, handled_requests->nelts);
+
+ /* Check that the requests were sent in the order we created them */
+ for (i = 0; i < sent_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(sent_requests, i, int);
+ CuAssertIntEquals(tc, i + 1, req_nr);
+ }
+
+ /* Check that the requests were received in the order we created them */
+ for (i = 0; i < handled_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(handled_requests, i, int);
+ CuAssertIntEquals(tc, i + 1, req_nr);
+ }
+
+ test_server_destroy(tb, test_pool);
+}
+
+/* Validate that priority requests are sent and completed before normal
+ requests. */
+static void test_serf_connection_priority_request_create(CuTest *tc)
+{
+ test_baton_t *tb;
+ serf_request_t *request1, *request2, *request3;
+ handler_baton_t handler_ctx, handler2_ctx, handler3_ctx;
+ apr_status_t status;
+ apr_pool_t *iter_pool;
+ apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
+ int i;
+ test_server_action_t action_list[] = {
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ CHUNCKED_REQUEST(1, "2")
+ CHUNCKED_REQUEST(1, "3")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ }
+ };
+
+ accepted_requests = apr_array_make(test_pool, 3, sizeof(int));
+ sent_requests = apr_array_make(test_pool, 3, sizeof(int));
+ handled_requests = apr_array_make(test_pool, 3, sizeof(int));
+
+ /* Set up a test context with a server */
+ status = test_server_create(&tb, action_list, 2, 0, NULL, NULL, NULL,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ handler_ctx.method = "GET";
+ handler_ctx.path = "/";
+ handler_ctx.done = FALSE;
+
+ handler_ctx.acceptor = accept_response;
+ handler_ctx.acceptor_baton = NULL;
+ handler_ctx.handler = handle_response;
+ handler_ctx.req_id = 2;
+ handler_ctx.accepted_requests = accepted_requests;
+ handler_ctx.sent_requests = sent_requests;
+ handler_ctx.handled_requests = handled_requests;
+ handler_ctx.use_proxy = FALSE;
+ handler_ctx.server_root = NULL;
+
+ request1 = serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler_ctx);
+
+ handler2_ctx = handler_ctx;
+ handler2_ctx.req_id = 3;
+
+ request2 = serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler2_ctx);
+ handler3_ctx = handler_ctx;
+ handler3_ctx.req_id = 1;
+
+ request3 = serf_connection_priority_request_create(tb->connection,
+ setup_request,
+ &handler3_ctx);
+
+ apr_pool_create(&iter_pool, test_pool);
+
+ while (!handler_ctx.done && !handler2_ctx.done && !handler3_ctx.done)
+ {
+ apr_pool_clear(iter_pool);
+
+ status = test_server_run(tb, 0, iter_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = serf_context_run(tb->context, 0, iter_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Debugging purposes only! */
+ serf_debug__closed_conn(tb->bkt_alloc);
+ }
+ apr_pool_destroy(iter_pool);
+
+ /* Check that all requests were received */
+ CuAssertIntEquals(tc, 3, sent_requests->nelts);
+ CuAssertIntEquals(tc, 3, accepted_requests->nelts);
+ CuAssertIntEquals(tc, 3, handled_requests->nelts);
+
+ /* Check that the requests were sent in the order we created them */
+ for (i = 0; i < sent_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(sent_requests, i, int);
+ CuAssertIntEquals(tc, i + 1, req_nr);
+ }
+
+ /* Check that the requests were received in the order we created them */
+ for (i = 0; i < handled_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(handled_requests, i, int);
+ CuAssertIntEquals(tc, i + 1, req_nr);
+ }
+
+ test_server_destroy(tb, test_pool);
+}
+
+/* Test that serf correctly handles the 'Connection:close' header when the
+ server is planning to close the connection. */
+#define NUM_REQUESTS 10
+static void test_serf_closed_connection(CuTest *tc)
+{
+ test_baton_t *tb;
+ apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
+ apr_status_t status;
+ handler_baton_t handler_ctx[NUM_REQUESTS];
+ int done = FALSE, i;
+
+ test_server_action_t action_list[] = {
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ CHUNCKED_REQUEST(1, "2")
+ CHUNCKED_REQUEST(1, "3")
+ CHUNCKED_REQUEST(1, "4")
+ CHUNCKED_REQUEST(1, "5")
+ CHUNCKED_REQUEST(1, "6")
+ CHUNCKED_REQUEST(1, "7")
+ CHUNCKED_REQUEST(1, "8")
+ CHUNCKED_REQUEST(1, "9")
+ CHUNCKED_REQUEST(2, "10")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ "HTTP/1.1 200 OK" CRLF
+ "Transfer-Encoding: chunked" CRLF
+ "Connection: close" CRLF
+ CRLF
+ "0" CRLF
+ CRLF
+ },
+ {SERVER_KILL_CONNECTION},
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ "HTTP/1.1 200 OK" CRLF
+ "Transfer-Encoding: chunked" CRLF
+ "Connection: close" CRLF
+ CRLF
+ "0" CRLF
+ CRLF
+ },
+ {SERVER_KILL_CONNECTION},
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ },
+ };
+
+ accepted_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
+ sent_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
+ handled_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
+
+ /* Set up a test context with a server. */
+ status = test_server_create(&tb, action_list, 6, 0, NULL, NULL, NULL,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ for (i = 0 ; i < NUM_REQUESTS ; i++) {
+ /* Send some requests on the connections */
+ handler_ctx[i].method = "GET";
+ handler_ctx[i].path = "/";
+ handler_ctx[i].done = FALSE;
+
+ handler_ctx[i].acceptor = accept_response;
+ handler_ctx[i].acceptor_baton = NULL;
+ handler_ctx[i].handler = handle_response;
+ handler_ctx[i].req_id = i+1;
+ handler_ctx[i].accepted_requests = accepted_requests;
+ handler_ctx[i].sent_requests = sent_requests;
+ handler_ctx[i].handled_requests = handled_requests;
+ handler_ctx[i].tb = tb;
+ handler_ctx[i].use_proxy = FALSE;
+ handler_ctx[i].server_root = NULL;
+
+ serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler_ctx[i]);
+ }
+
+ while (1) {
+ status = test_server_run(tb, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = serf_context_run(tb->context, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Debugging purposes only! */
+ serf_debug__closed_conn(tb->bkt_alloc);
+
+ done = TRUE;
+ for (i = 0 ; i < NUM_REQUESTS ; i++)
+ if (handler_ctx[i].done == FALSE) {
+ done = FALSE;
+ break;
+ }
+ if (done)
+ break;
+ }
+
+ /* Check that all requests were received */
+ CuAssertTrue(tc, sent_requests->nelts >= NUM_REQUESTS);
+ CuAssertIntEquals(tc, NUM_REQUESTS, accepted_requests->nelts);
+ CuAssertIntEquals(tc, NUM_REQUESTS, handled_requests->nelts);
+
+ /* Cleanup */
+ test_server_destroy(tb, test_pool);
+}
+#undef NUM_REQUESTS
+
+/* Test if serf is sending the request to the proxy, not to the server
+ directly. */
+static void test_serf_setup_proxy(CuTest *tc)
+{
+ test_baton_t *tb_server, *tb_proxy;
+ serf_request_t *request;
+ handler_baton_t handler_ctx;
+ apr_status_t status;
+ apr_pool_t *iter_pool;
+ apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
+ int i;
+ int numrequests = 1;
+ apr_sockaddr_t *proxy_address;
+ test_server_action_t *action_list_server = NULL;
+ test_server_action_t action_list_proxy[] = {
+ {SERVER_RECV,
+ "GET http://localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\
+ "Transfer-Encoding: chunked" CRLF\
+ "Host: localhost" CRLF\
+ CRLF\
+ "1" CRLF\
+ "1" CRLF\
+ "0" CRLF\
+ CRLF
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ }
+ };
+
+ accepted_requests = apr_array_make(test_pool, numrequests, sizeof(int));
+ sent_requests = apr_array_make(test_pool, numrequests, sizeof(int));
+ handled_requests = apr_array_make(test_pool, numrequests, sizeof(int));
+
+ /* Set up a test context with a server */
+ status = test_server_create(&tb_server, action_list_server, 2, 0,
+ "http://localhost:" SERV_PORT_STR, NULL,
+ NULL, test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Set up another test context for the proxy server */
+ status = apr_sockaddr_info_get(&proxy_address,
+ "localhost", APR_INET, 21212, 0,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = test_server_create(&tb_proxy, action_list_proxy, 2, 0,
+ NULL, proxy_address, NULL,
+ test_pool);
+
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ handler_ctx.method = "GET";
+ handler_ctx.path = "/";
+ handler_ctx.done = FALSE;
+
+ handler_ctx.acceptor = accept_response;
+ handler_ctx.acceptor_baton = NULL;
+ handler_ctx.handler = handle_response;
+ handler_ctx.req_id = 1;
+ handler_ctx.accepted_requests = accepted_requests;
+ handler_ctx.sent_requests = sent_requests;
+ handler_ctx.handled_requests = handled_requests;
+ handler_ctx.use_proxy = TRUE;
+ handler_ctx.server_root = "http://localhost:" SERV_PORT_STR;
+
+ /* Configure serf to use the proxy server */
+ serf_config_proxy(tb_server->context, proxy_address);
+
+ request = serf_connection_request_create(tb_server->connection,
+ setup_request,
+ &handler_ctx);
+
+ apr_pool_create(&iter_pool, test_pool);
+
+ while (!handler_ctx.done)
+ {
+ apr_pool_clear(iter_pool);
+
+ status = test_server_run(tb_server, 0, iter_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = test_server_run(tb_proxy, 0, iter_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = serf_context_run(tb_server->context, 0, iter_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Debugging purposes only! */
+ serf_debug__closed_conn(tb_server->bkt_alloc);
+ }
+ apr_pool_destroy(iter_pool);
+
+ /* Check that all requests were received */
+ CuAssertIntEquals(tc, numrequests, sent_requests->nelts);
+ CuAssertIntEquals(tc, numrequests, accepted_requests->nelts);
+ CuAssertIntEquals(tc, numrequests, handled_requests->nelts);
+
+ /* Check that the requests were sent in the order we created them */
+ for (i = 0; i < sent_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(sent_requests, i, int);
+ CuAssertIntEquals(tc, i + 1, req_nr);
+ }
+
+ /* Check that the requests were received in the order we created them */
+ for (i = 0; i < handled_requests->nelts; i++) {
+ int req_nr = APR_ARRAY_IDX(handled_requests, i, int);
+ CuAssertIntEquals(tc, i + 1, req_nr);
+ }
+
+ test_server_destroy(tb_server, test_pool);
+}
+
+/*****************************************************************************
+ * Test if we can make serf send requests one by one.
+ *****************************************************************************/
+
+/* Resend the first request 4 times by reducing the pipeline bandwidth to
+ one request at a time, and by adding the first request again at the start of
+ the outgoing queue. */
+static apr_status_t
+handle_response_keepalive_limit(serf_request_t *request,
+ serf_bucket_t *response,
+ void *handler_baton,
+ apr_pool_t *pool)
+{
+ handler_baton_t *ctx = handler_baton;
+
+ if (! response) {
+ return APR_SUCCESS;
+ }
+
+ while (1) {
+ apr_status_t status;
+ const char *data;
+ apr_size_t len;
+
+ status = serf_bucket_read(response, 2048, &data, &len);
+ if (SERF_BUCKET_READ_ERROR(status)) {
+ return status;
+ }
+
+ if (APR_STATUS_IS_EOF(status)) {
+ APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id;
+ ctx->done = TRUE;
+ if (ctx->req_id == 1 && ctx->handled_requests->nelts < 3) {
+ serf_connection_priority_request_create(ctx->tb->connection,
+ setup_request,
+ ctx);
+ ctx->done = FALSE;
+ }
+ return APR_EOF;
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+#define SEND_REQUESTS 5
+#define RCVD_REQUESTS 7
+static void test_keepalive_limit_one_by_one(CuTest *tc)
+{
+ test_baton_t *tb;
+ apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
+ apr_status_t status;
+ handler_baton_t handler_ctx[SEND_REQUESTS];
+ int done = FALSE, i;
+
+ test_server_action_t action_list[] = {
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "2")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "3")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "4")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "5")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ };
+
+ accepted_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
+ sent_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
+ handled_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
+
+ /* Set up a test context with a server. */
+ status = test_server_create(&tb, action_list, 14, 0, NULL, NULL, NULL,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ for (i = 0 ; i < SEND_REQUESTS ; i++) {
+ /* Send some requests on the connections */
+ handler_ctx[i].method = "GET";
+ handler_ctx[i].path = "/";
+ handler_ctx[i].done = FALSE;
+
+ handler_ctx[i].acceptor = accept_response;
+ handler_ctx[i].acceptor_baton = NULL;
+ handler_ctx[i].handler = handle_response_keepalive_limit;
+ handler_ctx[i].req_id = i+1;
+ handler_ctx[i].accepted_requests = accepted_requests;
+ handler_ctx[i].sent_requests = sent_requests;
+ handler_ctx[i].handled_requests = handled_requests;
+ handler_ctx[i].tb = tb;
+ handler_ctx[i].use_proxy = FALSE;
+ handler_ctx[i].server_root = NULL;
+
+ serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler_ctx[i]);
+ serf_connection_set_max_outstanding_requests(tb->connection, 1);
+ }
+
+ while (1) {
+ status = test_server_run(tb, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = serf_context_run(tb->context, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Debugging purposes only! */
+ serf_debug__closed_conn(tb->bkt_alloc);
+
+ done = TRUE;
+ for (i = 0 ; i < SEND_REQUESTS ; i++)
+ if (handler_ctx[i].done == FALSE) {
+ done = FALSE;
+ break;
+ }
+ if (done)
+ break;
+ }
+
+ /* Check that all requests were received */
+ CuAssertIntEquals(tc, RCVD_REQUESTS, sent_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, accepted_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, handled_requests->nelts);
+
+ /* Cleanup */
+ test_server_destroy(tb, test_pool);
+}
+#undef SEND_REQUESTS
+#undef RCVD_REQUESTS
+
+/*****************************************************************************
+ * Test if we can make serf first send requests one by one, and then change
+ * back to burst mode.
+ *****************************************************************************/
+#define SEND_REQUESTS 5
+#define RCVD_REQUESTS 7
+/* Resend the first request 2 times by reducing the pipeline bandwidth to
+ one request at a time, and by adding the first request again at the start of
+ the outgoing queue. */
+static apr_status_t
+handle_response_keepalive_limit_burst(serf_request_t *request,
+ serf_bucket_t *response,
+ void *handler_baton,
+ apr_pool_t *pool)
+{
+ handler_baton_t *ctx = handler_baton;
+
+ if (! response) {
+ return APR_SUCCESS;
+ }
+
+ while (1) {
+ apr_status_t status;
+ const char *data;
+ apr_size_t len;
+
+ status = serf_bucket_read(response, 2048, &data, &len);
+ if (SERF_BUCKET_READ_ERROR(status)) {
+ return status;
+ }
+
+ if (APR_STATUS_IS_EOF(status)) {
+ APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id;
+ ctx->done = TRUE;
+ if (ctx->req_id == 1 && ctx->handled_requests->nelts < 3) {
+ serf_connection_priority_request_create(ctx->tb->connection,
+ setup_request,
+ ctx);
+ ctx->done = FALSE;
+ }
+ else {
+ /* No more one-by-one. */
+ serf_connection_set_max_outstanding_requests(ctx->tb->connection,
+ 0);
+ }
+ return APR_EOF;
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+static void test_keepalive_limit_one_by_one_and_burst(CuTest *tc)
+{
+ test_baton_t *tb;
+ apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
+ apr_status_t status;
+ handler_baton_t handler_ctx[SEND_REQUESTS];
+ int done = FALSE, i;
+
+ test_server_action_t action_list[] = {
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ },
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "2")
+ CHUNCKED_REQUEST(1, "3")
+ CHUNCKED_REQUEST(1, "4")
+ CHUNCKED_REQUEST(1, "5")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ },
+ };
+
+ accepted_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
+ sent_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
+ handled_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int));
+
+ /* Set up a test context with a server. */
+ status = test_server_create(&tb, action_list, 8, 0, NULL, NULL, NULL,
+ test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ for (i = 0 ; i < SEND_REQUESTS ; i++) {
+ /* Send some requests on the connections */
+ handler_ctx[i].method = "GET";
+ handler_ctx[i].path = "/";
+ handler_ctx[i].done = FALSE;
+
+ handler_ctx[i].acceptor = accept_response;
+ handler_ctx[i].acceptor_baton = NULL;
+ handler_ctx[i].handler = handle_response_keepalive_limit_burst;
+ handler_ctx[i].req_id = i+1;
+ handler_ctx[i].accepted_requests = accepted_requests;
+ handler_ctx[i].sent_requests = sent_requests;
+ handler_ctx[i].handled_requests = handled_requests;
+ handler_ctx[i].tb = tb;
+ handler_ctx[i].use_proxy = FALSE;
+ handler_ctx[i].server_root = NULL;
+
+ serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler_ctx[i]);
+ serf_connection_set_max_outstanding_requests(tb->connection, 1);
+ }
+
+ while (1) {
+ status = test_server_run(tb, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = serf_context_run(tb->context, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Debugging purposes only! */
+ serf_debug__closed_conn(tb->bkt_alloc);
+
+ done = TRUE;
+ for (i = 0 ; i < SEND_REQUESTS ; i++)
+ if (handler_ctx[i].done == FALSE) {
+ done = FALSE;
+ break;
+ }
+ if (done)
+ break;
+ }
+
+ /* Check that all requests were received */
+ CuAssertIntEquals(tc, RCVD_REQUESTS, sent_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, accepted_requests->nelts);
+ CuAssertIntEquals(tc, RCVD_REQUESTS, handled_requests->nelts);
+
+ /* Cleanup */
+ test_server_destroy(tb, test_pool);
+}
+#undef SEND_REQUESTS
+#undef RCVD_REQUESTS
+
+#define NUM_REQUESTS 5
+typedef struct {
+ apr_off_t read;
+ apr_off_t written;
+} progress_baton_t;
+
+static void
+progress_cb(void *progress_baton, apr_off_t read, apr_off_t written)
+{
+ test_baton_t *tb = progress_baton;
+ progress_baton_t *pb = tb->user_baton;
+
+ pb->read = read;
+ pb->written = written;
+}
+
+static serf_bucket_t* progress_conn_setup(apr_socket_t *skt,
+ void *setup_baton,
+ apr_pool_t *pool)
+{
+ test_baton_t *tb = setup_baton;
+
+ return serf_context_bucket_socket_create(tb->context, skt, tb->bkt_alloc);
+}
+
+static void test_serf_progress_callback(CuTest *tc)
+{
+ test_baton_t *tb;
+ apr_array_header_t *accepted_requests, *handled_requests, *sent_requests;
+ apr_status_t status;
+ handler_baton_t handler_ctx[NUM_REQUESTS];
+ int done = FALSE, i;
+ progress_baton_t *pb;
+
+ test_server_action_t action_list[] = {
+ {SERVER_RECV,
+ CHUNCKED_REQUEST(1, "1")
+ CHUNCKED_REQUEST(1, "2")
+ CHUNCKED_REQUEST(1, "3")
+ CHUNCKED_REQUEST(1, "4")
+ CHUNCKED_REQUEST(1, "5")
+ },
+ {SERVER_SEND,
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_RESPONSE(1, "2")
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ CHUNKED_EMPTY_RESPONSE
+ },
+ };
+
+ accepted_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
+ sent_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
+ handled_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int));
+
+ /* Set up a test context with a server. */
+ status = test_server_create(&tb, action_list, 2, 0, NULL, NULL,
+ progress_conn_setup, test_pool);
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Set up the progress callback. */
+ pb = apr_pcalloc(test_pool, sizeof(*pb));
+ tb->user_baton = pb;
+ serf_context_set_progress_cb(tb->context, progress_cb, tb);
+
+ for (i = 0 ; i < NUM_REQUESTS ; i++) {
+ /* Send some requests on the connections */
+ handler_ctx[i].method = "GET";
+ handler_ctx[i].path = "/";
+ handler_ctx[i].done = FALSE;
+
+ handler_ctx[i].acceptor = accept_response;
+ handler_ctx[i].acceptor_baton = NULL;
+ handler_ctx[i].handler = handle_response;
+ handler_ctx[i].req_id = i+1;
+ handler_ctx[i].accepted_requests = accepted_requests;
+ handler_ctx[i].sent_requests = sent_requests;
+ handler_ctx[i].handled_requests = handled_requests;
+ handler_ctx[i].tb = tb;
+ handler_ctx[i].use_proxy = FALSE;
+ handler_ctx[i].server_root = NULL;
+
+ serf_connection_request_create(tb->connection,
+ setup_request,
+ &handler_ctx[i]);
+ }
+
+ while (1) {
+ status = test_server_run(tb, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ status = serf_context_run(tb->context, 0, test_pool);
+ if (APR_STATUS_IS_TIMEUP(status))
+ status = APR_SUCCESS;
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+
+ /* Debugging purposes only! */
+ serf_debug__closed_conn(tb->bkt_alloc);
+
+ done = TRUE;
+ for (i = 0 ; i < NUM_REQUESTS ; i++)
+ if (handler_ctx[i].done == FALSE) {
+ done = FALSE;
+ break;
+ }
+ if (done)
+ break;
+ }
+
+ /* Check that all requests were received */
+ CuAssertTrue(tc, sent_requests->nelts >= NUM_REQUESTS);
+ CuAssertIntEquals(tc, NUM_REQUESTS, accepted_requests->nelts);
+ CuAssertIntEquals(tc, NUM_REQUESTS, handled_requests->nelts);
+
+ /* Check that progress was reported. */
+ CuAssertTrue(tc, pb->written > 0);
+ CuAssertTrue(tc, pb->read > 0);
+
+ /* Cleanup */
+ test_server_destroy(tb, test_pool);
+}
+#undef NUM_REQUESTS
+
+CuSuite *test_context(void)
+{
+ CuSuite *suite = CuSuiteNew();
+
+ SUITE_ADD_TEST(suite, test_serf_connection_request_create);
+ SUITE_ADD_TEST(suite, test_serf_connection_priority_request_create);
+ SUITE_ADD_TEST(suite, test_serf_closed_connection);
+ SUITE_ADD_TEST(suite, test_serf_setup_proxy);
+ SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one);
+ SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one_and_burst);
+ SUITE_ADD_TEST(suite, test_serf_progress_callback);
+
+ return suite;
+}
--- /dev/null
+/* Copyright 2002-2007 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 TEST_SERF_H
+#define TEST_SERF_H
+
+#include "CuTest.h"
+
+#include <apr.h>
+#include <apr_pools.h>
+#include <apr_uri.h>
+
+#include "serf.h"
+
+/** These macros are provided by APR itself from version 1.3.
+ * Definitions are provided here for when using older versions of APR.
+ */
+
+/** index into an apr_array_header_t */
+#ifndef APR_ARRAY_IDX
+#define APR_ARRAY_IDX(ary,i,type) (((type *)(ary)->elts)[i])
+#endif
+
+/** easier array-pushing syntax */
+#ifndef APR_ARRAY_PUSH
+#define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary)))
+#endif
+
+extern apr_pool_t *test_pool;
+
+/* CuTest declarations */
+CuSuite *getsuite(void);
+
+CuSuite *test_context(void);
+CuSuite *test_buckets(void);
+CuSuite *test_ssl(void);
+
+/* Test setup declarations */
+
+#define CRLF "\r\n"
+
+#define CHUNCKED_REQUEST(len, body)\
+ "GET / HTTP/1.1" CRLF\
+ "Transfer-Encoding: chunked" CRLF\
+ CRLF\
+ #len CRLF\
+ body CRLF\
+ "0" CRLF\
+ CRLF
+
+#define CHUNKED_RESPONSE(len, body)\
+ "HTTP/1.1 200 OK" CRLF\
+ "Transfer-Encoding: chunked" CRLF\
+ CRLF\
+ #len CRLF\
+ body CRLF\
+ "0" CRLF\
+ CRLF
+
+#define CHUNKED_EMPTY_RESPONSE\
+ "HTTP/1.1 200 OK" CRLF\
+ "Transfer-Encoding: chunked" CRLF\
+ CRLF\
+ "0" CRLF\
+ CRLF
+
+typedef struct
+{
+ enum {
+ SERVER_RECV,
+ SERVER_SEND,
+ SERVER_KILL_CONNECTION
+ } kind;
+
+ const char *text;
+} test_server_action_t;
+
+typedef struct {
+ /* Pool for resource allocation. */
+ apr_pool_t *pool;
+
+ serf_context_t *context;
+ serf_connection_t *connection;
+ serf_bucket_alloc_t *bkt_alloc;
+ apr_int32_t options;
+
+ /* Array of actions which server will replay when client connected. */
+ test_server_action_t *action_list;
+ /* Size of action_list array. */
+ apr_size_t action_count;
+ /* Index of current action. */
+ apr_size_t cur_action;
+
+ /* Position in action buffer. */
+ apr_size_t action_buf_pos;
+
+ /* Address for server binding. */
+ apr_sockaddr_t *serv_addr;
+ apr_socket_t *serv_sock;
+
+ /* Accepted client socket. NULL if there is no client socket. */
+ apr_socket_t *client_sock;
+
+ /* An extra baton which can be freely used by tests. */
+ void *user_baton;
+
+} test_baton_t;
+
+#define TEST_SERVER_DUMP 1
+
+/* Default port for our test server. */
+#define SERV_PORT 12345
+#define SERV_PORT_STR "12345"
+
+apr_status_t test_server_create(test_baton_t **tb,
+ test_server_action_t *action_list,
+ apr_size_t action_count,
+ apr_int32_t options,
+ const char *host_url,
+ apr_sockaddr_t *address,
+ serf_connection_setup_t conn_setup,
+ apr_pool_t *pool);
+
+apr_status_t test_server_run(test_baton_t *tb,
+ apr_short_interval_time_t duration,
+ apr_pool_t *pool);
+
+apr_status_t test_server_destroy(test_baton_t *tb, apr_pool_t *pool);
+
+#ifndef APR_VERSION_AT_LEAST /* Introduced in APR 1.3.0 */
+#define APR_VERSION_AT_LEAST(major,minor,patch) \
+(((major) < APR_MAJOR_VERSION) \
+ || ((major) == APR_MAJOR_VERSION && (minor) < APR_MINOR_VERSION) \
+ || ((major) == APR_MAJOR_VERSION && (minor) == APR_MINOR_VERSION && \
+ (patch) <= APR_PATCH_VERSION))
+#endif /* APR_VERSION_AT_LEAST */
+
+#endif /* TEST_SERF_H */
--- /dev/null
+/* Copyright 2008 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.
+ */
+
+#include <apr.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+
+#include "serf.h"
+#include "serf_bucket_types.h"
+
+#include "test_serf.h"
+
+#ifdef WIN32
+/* Include this file to allow running a Debug build of serf with a Release
+ build of OpenSSL. */
+#include <openssl/applink.c>
+#endif
+
+/* Test that loading a custom CA certificate file works. */
+static void test_ssl_load_cert_file(CuTest *tc)
+{
+ serf_ssl_certificate_t *cert = NULL;
+ apr_status_t status = serf_ssl_load_cert_file(&cert, "test/serftestca.pem",
+ test_pool);
+
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+ CuAssertPtrNotNull(tc, cert);
+}
+
+/* Test that reading a custom CA certificate file works. */
+static void test_ssl_cert_subject(CuTest *tc)
+{
+ apr_pool_t *subpool;
+ apr_hash_t *subject;
+ serf_ssl_certificate_t *cert = NULL;
+ apr_status_t status;
+
+ apr_pool_create(&subpool, test_pool);
+ status = serf_ssl_load_cert_file(&cert, "test/serftestca.pem", subpool);
+
+ CuAssertIntEquals(tc, APR_SUCCESS, status);
+ CuAssertPtrNotNull(tc, cert);
+
+ subject = serf_ssl_cert_subject(cert, subpool);
+ CuAssertStrEquals(tc, "Test Suite",
+ apr_hash_get(subject, "OU", APR_HASH_KEY_STRING));
+ CuAssertStrEquals(tc, "In Serf we trust, Inc.",
+ apr_hash_get(subject, "O", APR_HASH_KEY_STRING));
+ CuAssertStrEquals(tc, "Mechelen",
+ apr_hash_get(subject, "L", APR_HASH_KEY_STRING));
+ CuAssertStrEquals(tc, "Antwerp",
+ apr_hash_get(subject, "ST", APR_HASH_KEY_STRING));
+ CuAssertStrEquals(tc, "BE",
+ apr_hash_get(subject, "C", APR_HASH_KEY_STRING));
+ CuAssertStrEquals(tc, "serf@example.com",
+ apr_hash_get(subject, "E", APR_HASH_KEY_STRING));
+
+ apr_pool_destroy(subpool);
+}
+
+CuSuite *test_ssl(void)
+{
+ CuSuite *suite = CuSuiteNew();
+
+ SUITE_ADD_TEST(suite, test_ssl_load_cert_file);
+ SUITE_ADD_TEST(suite, test_ssl_cert_subject);
+
+ return suite;
+}
--- /dev/null
+/* Copyright 2002-2007 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.
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include <apr_poll.h>
+#include <apr_version.h>
+#include <stdlib.h>
+
+#include "serf.h"
+
+#include "test_serf.h"
+
+/*****************************************************************************/
+/* Server setup functions
+ */
+
+/* Default implementation of a serf_connection_closed_t callback. */
+static void default_closed_connection(serf_connection_t *conn,
+ void *closed_baton,
+ apr_status_t why,
+ apr_pool_t *pool)
+{
+ if (why) {
+ abort();
+ }
+}
+
+/* Default implementation of a serf_connection_setup_t callback. */
+static serf_bucket_t* default_conn_setup(apr_socket_t *skt,
+ void *setup_baton,
+ apr_pool_t *pool)
+{
+ test_baton_t *ctx = setup_baton;
+
+ return serf_bucket_socket_create(skt, ctx->bkt_alloc);
+}
+
+static apr_status_t get_server_address(apr_sockaddr_t **address,
+ apr_pool_t *pool)
+{
+ return apr_sockaddr_info_get(address,
+ "localhost", APR_INET, SERV_PORT, 0,
+ pool);
+}
+
+static void next_action(test_baton_t *tb)
+{
+ tb->cur_action++;
+ tb->action_buf_pos = 0;
+}
+
+static apr_status_t replay(test_baton_t *tb,
+ apr_pool_t *pool)
+{
+ apr_status_t status = APR_SUCCESS;
+ test_server_action_t *action;
+
+ if (tb->cur_action >= tb->action_count) {
+ char buf[128];
+ apr_size_t len = sizeof(buf);
+
+ status = apr_socket_recv(tb->client_sock, buf, &len);
+ if (! APR_STATUS_IS_EAGAIN(status)) {
+ /* we're out of actions! */
+ printf("Received more requests than expected\n");
+
+ return APR_EGENERAL;
+ }
+
+ return status;
+ }
+
+ if (tb->action_list == NULL)
+ {
+ /* we're not expecting any requests to reach this server! */
+ printf("Received request where none was expected\n");
+
+ return APR_EGENERAL;
+ }
+
+ action = &tb->action_list[tb->cur_action];
+
+ if (action->kind == SERVER_RECV)
+ {
+ apr_size_t msg_len, len;
+ char buf[128];
+
+ msg_len = strlen(action->text);
+
+ len = msg_len - tb->action_buf_pos;
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
+ status = apr_socket_recv(tb->client_sock, buf, &len);
+ if (status != APR_SUCCESS)
+ return status;
+
+ if (tb->options & TEST_SERVER_DUMP)
+ fwrite(buf, len, 1, stdout);
+
+ if (strncmp(buf, action->text + tb->action_buf_pos, len) != 0) {
+ /* ## TODO: Better diagnostics. */
+ printf("Expected: (\n");
+ fwrite(action->text + tb->action_buf_pos, len, 1, stdout);
+ printf(")\n");
+ printf("Actual: (\n");
+ fwrite(buf, len, 1, stdout);
+ printf(")\n");
+
+ return APR_EGENERAL;
+ }
+
+ tb->action_buf_pos += len;
+
+ if (tb->action_buf_pos >= msg_len)
+ next_action(tb);
+ }
+ else if (action->kind == SERVER_SEND) {
+ apr_size_t msg_len;
+ apr_size_t len;
+
+ msg_len = strlen(action->text);
+ len = msg_len - tb->action_buf_pos;
+
+ status = apr_socket_send(tb->client_sock,
+ action->text + tb->action_buf_pos, &len);
+ if (status != APR_SUCCESS)
+ return status;
+
+ if (tb->options & TEST_SERVER_DUMP)
+ fwrite(action->text + tb->action_buf_pos, len, 1, stdout);
+
+ tb->action_buf_pos += len;
+
+ if (tb->action_buf_pos >= msg_len)
+ next_action(tb);
+ }
+ else if (action->kind == SERVER_KILL_CONNECTION) {
+ apr_socket_close(tb->client_sock);
+ tb->client_sock = NULL;
+ next_action(tb);
+ }
+ else {
+ abort();
+ }
+
+ return status;
+}
+
+apr_status_t test_server_run(test_baton_t *tb,
+ apr_short_interval_time_t duration,
+ apr_pool_t *pool)
+{
+ apr_status_t status;
+ apr_pollset_t *pollset;
+ apr_int32_t num;
+ const apr_pollfd_t *desc;
+
+ /* create a new pollset */
+ status = apr_pollset_create(&pollset, 32, pool, 0);
+ if (status != APR_SUCCESS)
+ return status;
+
+ /* Don't accept new connection while processing client connection. At
+ least for present time.*/
+ if (tb->client_sock) {
+ apr_pollfd_t pfd = { pool, APR_POLL_SOCKET, APR_POLLIN | APR_POLLOUT, 0,
+ { NULL }, NULL };
+ pfd.desc.s = tb->client_sock;
+ status = apr_pollset_add(pollset, &pfd);
+ if (status != APR_SUCCESS)
+ goto cleanup;
+ }
+ else {
+ apr_pollfd_t pfd = { pool, APR_POLL_SOCKET, APR_POLLIN, 0,
+ { NULL }, NULL };
+ pfd.desc.s = tb->serv_sock;
+ status = apr_pollset_add(pollset, &pfd);
+ if (status != APR_SUCCESS)
+ goto cleanup;
+ }
+
+ status = apr_pollset_poll(pollset, APR_USEC_PER_SEC >> 1, &num, &desc);
+ if (status != APR_SUCCESS)
+ goto cleanup;
+
+ while (num--) {
+ if (desc->desc.s == tb->serv_sock) {
+ status = apr_socket_accept(&tb->client_sock, tb->serv_sock,
+ tb->pool);
+ if (status != APR_SUCCESS)
+ goto cleanup;
+
+ apr_socket_opt_set(tb->client_sock, APR_SO_NONBLOCK, 1);
+ apr_socket_timeout_set(tb->client_sock, 0);
+
+ status = APR_SUCCESS;
+ goto cleanup;
+ }
+
+ if (desc->desc.s == tb->client_sock) {
+ /* Replay data to socket. */
+ status = replay(tb, pool);
+
+ if (APR_STATUS_IS_EOF(status)) {
+ apr_socket_close(tb->client_sock);
+ tb->client_sock = NULL;
+ }
+ else if (APR_STATUS_IS_EAGAIN(status)) {
+ status = APR_SUCCESS;
+ }
+ else if (status != APR_SUCCESS) {
+ /* Real error. */
+ goto cleanup;
+ }
+ }
+
+ desc++;
+ }
+
+cleanup:
+ apr_pollset_destroy(pollset);
+
+ return status;
+}
+
+/* Start a TCP server on port SERV_PORT in thread THREAD. srv_replay is a array
+ of action to replay when connection started. replay_count is count of
+ actions in srv_replay. */
+static apr_status_t prepare_server(test_baton_t *tb,
+ apr_pool_t *pool)
+{
+ apr_status_t status;
+ apr_socket_t *serv_sock;
+
+ /* create server socket */
+#if APR_VERSION_AT_LEAST(1, 0, 0)
+ status = apr_socket_create(&serv_sock, APR_INET, SOCK_STREAM, 0, pool);
+#else
+ status = apr_socket_create(&serv_sock, APR_INET, SOCK_STREAM, pool);
+#endif
+
+ if (status != APR_SUCCESS)
+ return status;
+
+ apr_socket_opt_set(serv_sock, APR_SO_NONBLOCK, 1);
+ apr_socket_timeout_set(serv_sock, 0);
+ apr_socket_opt_set(serv_sock, APR_SO_REUSEADDR, 1);
+
+ status = apr_socket_bind(serv_sock, tb->serv_addr);
+ if (status != APR_SUCCESS)
+ return status;
+
+ /* Start replay from first action. */
+ tb->cur_action = 0;
+ tb->action_buf_pos = 0;
+
+ /* listen for clients */
+ apr_socket_listen(serv_sock, SOMAXCONN);
+ if (status != APR_SUCCESS)
+ return status;
+
+ tb->serv_sock = serv_sock;
+ tb->client_sock = NULL;
+ return APR_SUCCESS;
+}
+
+/*****************************************************************************/
+
+apr_status_t test_server_create(test_baton_t **tb_p,
+ test_server_action_t *action_list,
+ apr_size_t action_count,
+ apr_int32_t options,
+ const char *host_url,
+ apr_sockaddr_t *address,
+ serf_connection_setup_t conn_setup,
+ apr_pool_t *pool)
+{
+ apr_status_t status;
+ test_baton_t *tb;
+
+ tb = apr_palloc(pool, sizeof(*tb));
+ *tb_p = tb;
+
+ if (address) {
+ tb->serv_addr = address;
+ }
+ else {
+ status = get_server_address(&tb->serv_addr, pool);
+ if (status != APR_SUCCESS)
+ return status;
+ }
+
+ tb->pool = pool;
+ tb->options = options;
+ tb->context = serf_context_create(pool);
+ tb->bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
+ if (host_url) {
+ apr_uri_t url;
+ status = apr_uri_parse(pool, host_url, &url);
+ if (status != APR_SUCCESS)
+ return status;
+
+ status = serf_connection_create2(&tb->connection, tb->context,
+ url,
+ conn_setup ? conn_setup :
+ default_conn_setup,
+ tb,
+ default_closed_connection,
+ tb,
+ pool);
+ if (status != APR_SUCCESS)
+ return status;
+ } else {
+ tb->connection = serf_connection_create(tb->context,
+ tb->serv_addr,
+ conn_setup ? conn_setup :
+ default_conn_setup,
+ tb,
+ default_closed_connection,
+ tb,
+ pool);
+ }
+ tb->action_list = action_list;
+ tb->action_count = action_count;
+
+ /* Prepare a server. */
+ status = prepare_server(tb, pool);
+ if (status != APR_SUCCESS)
+ return status;
+
+ return APR_SUCCESS;
+}
+
+apr_status_t test_server_destroy(test_baton_t *tb, apr_pool_t *pool)
+{
+ serf_connection_close(tb->connection);
+
+ apr_socket_close(tb->serv_sock);
+
+ if (tb->client_sock) {
+ apr_socket_close(tb->client_sock);
+ }
+
+ return APR_SUCCESS;
+}