summaryrefslogtreecommitdiffstats
path: root/contrib/serf/buckets
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2014-02-22 18:55:49 +0000
committerpeter <peter@FreeBSD.org>2014-02-22 18:55:49 +0000
commit92739d7a0b63f570534b21b1dcc909457336c381 (patch)
tree3f025a453a6555531748fc481d3388e91cee0004 /contrib/serf/buckets
parent30ff5acc637e49d3458503caf8ca7871e2910ecb (diff)
downloadFreeBSD-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.c37
-rw-r--r--contrib/serf/buckets/response_buckets.c40
-rw-r--r--contrib/serf/buckets/socket_buckets.c2
-rw-r--r--contrib/serf/buckets/ssl_buckets.c50
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;
OpenPOWER on IntegriCloud