diff options
author | peter <peter@FreeBSD.org> | 2014-02-22 18:55:49 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2014-02-22 18:55:49 +0000 |
commit | 92739d7a0b63f570534b21b1dcc909457336c381 (patch) | |
tree | 3f025a453a6555531748fc481d3388e91cee0004 /contrib/serf/buckets | |
parent | 30ff5acc637e49d3458503caf8ca7871e2910ecb (diff) | |
download | FreeBSD-src-92739d7a0b63f570534b21b1dcc909457336c381.zip FreeBSD-src-92739d7a0b63f570534b21b1dcc909457336c381.tar.gz |
MFC r262324: serf 1.3.4 - improve SSL handling with svn-1.8.8 and other
speedups and quality of life fixes.
Diffstat (limited to 'contrib/serf/buckets')
-rw-r--r-- | contrib/serf/buckets/headers_buckets.c | 37 | ||||
-rw-r--r-- | contrib/serf/buckets/response_buckets.c | 40 | ||||
-rw-r--r-- | contrib/serf/buckets/socket_buckets.c | 2 | ||||
-rw-r--r-- | contrib/serf/buckets/ssl_buckets.c | 50 |
4 files changed, 95 insertions, 34 deletions
diff --git a/contrib/serf/buckets/headers_buckets.c b/contrib/serf/buckets/headers_buckets.c index 6401f7f..04e64d1 100644 --- a/contrib/serf/buckets/headers_buckets.c +++ b/contrib/serf/buckets/headers_buckets.c @@ -20,6 +20,8 @@ #include "serf.h" #include "serf_bucket_util.h" +#include "serf_private.h" /* for serf__bucket_headers_remove */ + typedef struct header_list { const char *header; @@ -37,6 +39,7 @@ typedef struct header_list { typedef struct { header_list_t *list; + header_list_t *last; header_list_t *cur_read; enum { @@ -60,6 +63,7 @@ serf_bucket_t *serf_bucket_headers_create( ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); ctx->list = NULL; + ctx->last = NULL; ctx->state = READ_START; return serf_bucket_create(&serf_bucket_type_headers, allocator, ctx); @@ -71,7 +75,6 @@ void serf_bucket_headers_setx( const char *value, apr_size_t value_size, int value_copy) { headers_context_t *ctx = bkt->data; - header_list_t *iter = ctx->list; header_list_t *hdr; #if 0 @@ -105,13 +108,12 @@ void serf_bucket_headers_setx( } /* Add the new header at the end of the list. */ - while (iter && iter->next) { - iter = iter->next; - } - if (iter) - iter->next = hdr; + if (ctx->last) + ctx->last->next = hdr; else ctx->list = hdr; + + ctx->last = hdr; } void serf_bucket_headers_set( @@ -191,6 +193,29 @@ const char *serf_bucket_headers_get( return val; } +void serf__bucket_headers_remove(serf_bucket_t *bucket, const char *header) +{ + headers_context_t *ctx = bucket->data; + header_list_t *scan = ctx->list, *prev = NULL; + + /* Find and delete all items with the same header (case insensitive) */ + while (scan) { + if (strcasecmp(scan->header, header) == 0) { + if (prev) { + prev->next = scan->next; + } else { + ctx->list = scan->next; + } + if (ctx->last == scan) { + ctx->last = NULL; + } + } else { + prev = scan; + } + scan = scan->next; + } +} + void serf_bucket_headers_do( serf_bucket_t *headers_bucket, serf_bucket_headers_do_callback_fn_t func, diff --git a/contrib/serf/buckets/response_buckets.c b/contrib/serf/buckets/response_buckets.c index d343a4c..39518bb 100644 --- a/contrib/serf/buckets/response_buckets.c +++ b/contrib/serf/buckets/response_buckets.c @@ -43,6 +43,29 @@ typedef struct { int head_req; /* Was this a HEAD request? */ } response_context_t; +/* Returns 1 if according to RFC2626 this response can have a body, 0 if it + must not have a body. */ +static int expect_body(response_context_t *ctx) +{ + if (ctx->head_req) + return 0; + + /* 100 Continue and 101 Switching Protocols */ + if (ctx->sl.code >= 100 && ctx->sl.code < 200) + return 0; + + /* 204 No Content */ + if (ctx->sl.code == 204) + return 0; + + /* 205? */ + + /* 304 Not Modified */ + if (ctx->sl.code == 304) + return 0; + + return 1; +} serf_bucket_t *serf_bucket_response_create( serf_bucket_t *stream, @@ -238,6 +261,15 @@ static apr_status_t run_machine(serf_bucket_t *bkt, response_context_t *ctx) /* Advance the state. */ ctx->state = STATE_BODY; + /* If this is a response to a HEAD request, or code == 1xx,204 or304 + then we don't receive a real body. */ + if (!expect_body(ctx)) { + ctx->body = serf_bucket_simple_create(NULL, 0, NULL, NULL, + bkt->allocator); + ctx->state = STATE_BODY; + break; + } + ctx->body = serf_bucket_barrier_create(ctx->stream, bkt->allocator); @@ -261,10 +293,6 @@ static apr_status_t run_machine(serf_bucket_t *bkt, response_context_t *ctx) ctx->body = serf_bucket_dechunk_create(ctx->body, bkt->allocator); } - - if (!v && (ctx->sl.code == 204 || ctx->sl.code == 304)) { - ctx->state = STATE_DONE; - } } v = serf_bucket_headers_get(ctx->headers, "Content-Encoding"); if (v) { @@ -280,10 +308,6 @@ static apr_status_t run_machine(serf_bucket_t *bkt, response_context_t *ctx) SERF_DEFLATE_DEFLATE); } } - /* If we're a HEAD request, we don't receive a body. */ - if (ctx->head_req) { - ctx->state = STATE_DONE; - } } break; case STATE_BODY: diff --git a/contrib/serf/buckets/socket_buckets.c b/contrib/serf/buckets/socket_buckets.c index ef718af..d0facda 100644 --- a/contrib/serf/buckets/socket_buckets.c +++ b/contrib/serf/buckets/socket_buckets.c @@ -50,7 +50,7 @@ static apr_status_t socket_reader(void *baton, apr_size_t bufsize, "--- socket_recv:\n%.*s\n-(%d)-\n", *len, buf, *len); - if (ctx->progress_func) + if (ctx->progress_func && *len) ctx->progress_func(ctx->progress_baton, *len, 0); return status; diff --git a/contrib/serf/buckets/ssl_buckets.c b/contrib/serf/buckets/ssl_buckets.c index d2ced94..1a27d3f 100644 --- a/contrib/serf/buckets/ssl_buckets.c +++ b/contrib/serf/buckets/ssl_buckets.c @@ -463,6 +463,7 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx) case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_INVALID_CA: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: failures |= SERF_SSL_CERT_UNKNOWNCA; break; case X509_V_ERR_CERT_REVOKED: @@ -958,16 +959,24 @@ static apr_status_t cleanup_ssl(void *data) #endif -static apr_uint32_t have_init_ssl = 0; +#if !APR_VERSION_AT_LEAST(1,0,0) +#define apr_atomic_cas32(mem, with, cmp) apr_atomic_cas(mem, with, cmp) +#endif + +enum ssl_init_e +{ + INIT_UNINITIALIZED = 0, + INIT_BUSY = 1, + INIT_DONE = 2 +}; + +static volatile apr_uint32_t have_init_ssl = INIT_UNINITIALIZED; static void init_ssl_libraries(void) { apr_uint32_t val; -#if APR_VERSION_AT_LEAST(1,0,0) - val = apr_atomic_xchg32(&have_init_ssl, 1); -#else - val = apr_atomic_cas(&have_init_ssl, 1, 0); -#endif + + val = apr_atomic_cas32(&have_init_ssl, INIT_BUSY, INIT_UNINITIALIZED); if (!val) { #if APR_HAS_THREADS @@ -1015,6 +1024,19 @@ static void init_ssl_libraries(void) apr_pool_cleanup_register(ssl_pool, NULL, cleanup_ssl, cleanup_ssl); #endif + apr_atomic_cas32(&have_init_ssl, INIT_DONE, INIT_BUSY); + } + else + { + /* Make sure we don't continue before the initialization in another + thread has completed */ + while (val != INIT_DONE) { + apr_sleep(APR_USEC_PER_SEC / 1000); + + val = apr_atomic_cas32(&have_init_ssl, + INIT_UNINITIALIZED, + INIT_UNINITIALIZED); + } } } @@ -1198,21 +1220,16 @@ void serf_ssl_server_cert_chain_callback_set( context->server_cert_userdata = data; } -static serf_ssl_context_t *ssl_init_context(void) +static serf_ssl_context_t *ssl_init_context(serf_bucket_alloc_t *allocator) { serf_ssl_context_t *ssl_ctx; - apr_pool_t *pool; - serf_bucket_alloc_t *allocator; init_ssl_libraries(); - apr_pool_create(&pool, NULL); - allocator = serf_bucket_allocator_create(pool, NULL, NULL); - ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx)); ssl_ctx->refcount = 0; - ssl_ctx->pool = pool; + ssl_ctx->pool = serf_bucket_allocator_get_pool(allocator); ssl_ctx->allocator = allocator; ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method()); @@ -1269,8 +1286,6 @@ static serf_ssl_context_t *ssl_init_context(void) static apr_status_t ssl_free_context( serf_ssl_context_t *ssl_ctx) { - apr_pool_t *p; - /* If never had the pending buckets, don't try to free them. */ if (ssl_ctx->decrypt.pending != NULL) { serf_bucket_destroy(ssl_ctx->decrypt.pending); @@ -1283,10 +1298,7 @@ static apr_status_t ssl_free_context( SSL_free(ssl_ctx->ssl); SSL_CTX_free(ssl_ctx->ctx); - p = ssl_ctx->pool; - serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx); - apr_pool_destroy(p); return APR_SUCCESS; } @@ -1300,7 +1312,7 @@ static serf_bucket_t * serf_bucket_ssl_create( ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); if (!ssl_ctx) { - ctx->ssl_ctx = ssl_init_context(); + ctx->ssl_ctx = ssl_init_context(allocator); } else { ctx->ssl_ctx = ssl_ctx; |