summaryrefslogtreecommitdiffstats
path: root/contrib/serf/buckets
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2013-08-02 19:21:46 +0000
committerpeter <peter@FreeBSD.org>2013-08-02 19:21:46 +0000
commitbce4a8587da654a7a12e36d4a6822cd999c0aafc (patch)
tree27dab9bf5d6ff996ae09bc981c7d20022b26fa50 /contrib/serf/buckets
parent5750092edd0958adc875d6012f6e656a430e71c6 (diff)
parent089059a1407b9504b9fdd10f3b602b94d36ed187 (diff)
downloadFreeBSD-src-bce4a8587da654a7a12e36d4a6822cd999c0aafc.zip
FreeBSD-src-bce4a8587da654a7a12e36d4a6822cd999c0aafc.tar.gz
Update serf 1.2.1 -> 1.3.0 for svn
Diffstat (limited to 'contrib/serf/buckets')
-rw-r--r--contrib/serf/buckets/aggregate_buckets.c96
-rw-r--r--contrib/serf/buckets/buckets.c28
-rw-r--r--contrib/serf/buckets/dechunk_buckets.c4
-rw-r--r--contrib/serf/buckets/headers_buckets.c4
-rw-r--r--contrib/serf/buckets/limit_buckets.c9
-rw-r--r--contrib/serf/buckets/request_buckets.c11
-rw-r--r--contrib/serf/buckets/response_buckets.c2
-rw-r--r--contrib/serf/buckets/simple_buckets.c17
-rw-r--r--contrib/serf/buckets/ssl_buckets.c49
9 files changed, 184 insertions, 36 deletions
diff --git a/contrib/serf/buckets/aggregate_buckets.c b/contrib/serf/buckets/aggregate_buckets.c
index d9d15a3..2ae3fd5 100644
--- a/contrib/serf/buckets/aggregate_buckets.c
+++ b/contrib/serf/buckets/aggregate_buckets.c
@@ -353,16 +353,104 @@ static apr_status_t serf_aggregate_readline(serf_bucket_t *bucket,
int acceptable, int *found,
const char **data, apr_size_t *len)
{
- /* Follow pattern from serf_aggregate_read. */
- return APR_ENOTIMPL;
+ aggregate_context_t *ctx = bucket->data;
+ apr_status_t status;
+
+ cleanup_aggregate(ctx, bucket->allocator);
+
+ do {
+ serf_bucket_t *head;
+
+ *len = 0;
+
+ if (!ctx->list) {
+ if (ctx->hold_open) {
+ return ctx->hold_open(ctx->hold_open_baton, bucket);
+ }
+ else {
+ return APR_EOF;
+ }
+ }
+
+ head = ctx->list->bucket;
+
+ status = serf_bucket_readline(head, acceptable, found,
+ data, len);
+ if (SERF_BUCKET_READ_ERROR(status))
+ return status;
+
+ if (status == APR_EOF) {
+ bucket_list_t *next_list;
+
+ /* head bucket is empty, move to to-be-cleaned-up list. */
+ next_list = ctx->list->next;
+ ctx->list->next = ctx->done;
+ ctx->done = ctx->list;
+ ctx->list = next_list;
+
+ /* If we have no more in our list, return EOF. */
+ if (!ctx->list) {
+ if (ctx->hold_open) {
+ return ctx->hold_open(ctx->hold_open_baton, bucket);
+ }
+ else {
+ return APR_EOF;
+ }
+ }
+
+ /* we read something, so bail out and let the appl. read again. */
+ if (*len)
+ status = APR_SUCCESS;
+ }
+
+ /* continue with APR_SUCCESS or APR_EOF and no data read yet. */
+ } while (!*len && status != APR_EAGAIN);
+
+ return status;
}
static apr_status_t serf_aggregate_peek(serf_bucket_t *bucket,
const char **data,
apr_size_t *len)
{
- /* Follow pattern from serf_aggregate_read. */
- return APR_ENOTIMPL;
+ aggregate_context_t *ctx = bucket->data;
+ serf_bucket_t *head;
+ apr_status_t status;
+
+ cleanup_aggregate(ctx, bucket->allocator);
+
+ /* Peek the first bucket in the list, if any. */
+ if (!ctx->list) {
+ *len = 0;
+ if (ctx->hold_open) {
+ status = ctx->hold_open(ctx->hold_open_baton, bucket);
+ if (status == APR_EAGAIN)
+ status = APR_SUCCESS;
+ return status;
+ }
+ else {
+ return APR_EOF;
+ }
+ }
+
+ head = ctx->list->bucket;
+
+ status = serf_bucket_peek(head, data, len);
+
+ if (status == APR_EOF) {
+ if (ctx->list->next) {
+ status = APR_SUCCESS;
+ } else {
+ if (ctx->hold_open) {
+ status = ctx->hold_open(ctx->hold_open_baton, bucket);
+ if (status == APR_EAGAIN)
+ status = APR_SUCCESS;
+ return status;
+ }
+ }
+ }
+
+ return status;
}
static serf_bucket_t * serf_aggregate_read_bucket(
diff --git a/contrib/serf/buckets/buckets.c b/contrib/serf/buckets/buckets.c
index 72b3913..88e256b 100644
--- a/contrib/serf/buckets/buckets.c
+++ b/contrib/serf/buckets/buckets.c
@@ -17,7 +17,7 @@
#include "serf.h"
#include "serf_bucket_util.h"
-
+#include "serf_private.h"
serf_bucket_t *serf_bucket_create(
const serf_bucket_type_t *type,
@@ -155,6 +155,32 @@ char *serf_bstrdup(serf_bucket_alloc_t *allocator,
return newstr;
}
+char *serf_bstrcatv(serf_bucket_alloc_t *allocator, struct iovec *vec,
+ int vecs, apr_size_t *bytes_written)
+{
+ int i;
+ apr_size_t new_len = 0;
+ char *c, *newstr;
+
+ for (i = 0; i < vecs; i++) {
+ new_len += vec[i].iov_len;
+ }
+
+ /* It's up to the caller to free this memory later. */
+ newstr = serf_bucket_mem_alloc(allocator, new_len);
+
+ c = newstr;
+ for (i = 0; i < vecs; i++) {
+ memcpy(c, vec[i].iov_base, vec[i].iov_len);
+ c += vec[i].iov_len;
+ }
+
+ if (bytes_written) {
+ *bytes_written = c - newstr;
+ }
+
+ return newstr;
+}
/* ==================================================================== */
diff --git a/contrib/serf/buckets/dechunk_buckets.c b/contrib/serf/buckets/dechunk_buckets.c
index 262cffb..eda1e22 100644
--- a/contrib/serf/buckets/dechunk_buckets.c
+++ b/contrib/serf/buckets/dechunk_buckets.c
@@ -162,6 +162,9 @@ static apr_status_t serf_dechunk_read(serf_bucket_t *bucket,
ctx->state = STATE_SIZE;
}
+ /* Don't return the CR of CRLF to the caller! */
+ *len = 0;
+
if (status)
return status;
@@ -169,6 +172,7 @@ static apr_status_t serf_dechunk_read(serf_bucket_t *bucket,
case STATE_DONE:
/* Just keep returning EOF */
+ *len = 0;
return APR_EOF;
default:
diff --git a/contrib/serf/buckets/headers_buckets.c b/contrib/serf/buckets/headers_buckets.c
index 1c37ef0..6401f7f 100644
--- a/contrib/serf/buckets/headers_buckets.c
+++ b/contrib/serf/buckets/headers_buckets.c
@@ -325,8 +325,10 @@ static apr_status_t serf_headers_read(serf_bucket_t *bucket,
apr_size_t avail;
select_value(ctx, data, &avail);
- if (ctx->state == READ_DONE)
+ if (ctx->state == READ_DONE) {
+ *len = avail;
return APR_EOF;
+ }
if (requested >= avail) {
/* return everything from this chunk */
diff --git a/contrib/serf/buckets/limit_buckets.c b/contrib/serf/buckets/limit_buckets.c
index d2e6166..70b7efb 100644
--- a/contrib/serf/buckets/limit_buckets.c
+++ b/contrib/serf/buckets/limit_buckets.c
@@ -17,14 +17,7 @@
#include "serf.h"
#include "serf_bucket_util.h"
-
-/* Older versions of APR do not have this macro. */
-#ifdef APR_SIZE_MAX
-#define REQUESTED_MAX APR_SIZE_MAX
-#else
-#define REQUESTED_MAX (~((apr_size_t)0))
-#endif
-
+#include "serf_private.h"
typedef struct {
serf_bucket_t *stream;
diff --git a/contrib/serf/buckets/request_buckets.c b/contrib/serf/buckets/request_buckets.c
index be010c0..912da8a 100644
--- a/contrib/serf/buckets/request_buckets.c
+++ b/contrib/serf/buckets/request_buckets.c
@@ -105,14 +105,9 @@ static void serialize_data(serf_bucket_t *bucket)
iov[3].iov_base = " HTTP/1.1\r\n";
iov[3].iov_len = sizeof(" HTTP/1.1\r\n") - 1;
- /* ### pool allocation! */
- new_data = apr_pstrcatv(serf_bucket_allocator_get_pool(bucket->allocator),
- iov, 4, &nbytes);
-
- /* Create a new bucket for this string. A free function isn't needed
- * since the string is residing in a pool.
- */
- new_bucket = SERF_BUCKET_SIMPLE_STRING_LEN(new_data, nbytes,
+ /* Create a new bucket for this string with a flat string. */
+ new_data = serf_bstrcatv(bucket->allocator, iov, 4, &nbytes);
+ new_bucket = serf_bucket_simple_own_create(new_data, nbytes,
bucket->allocator);
/* Build up the new bucket structure.
diff --git a/contrib/serf/buckets/response_buckets.c b/contrib/serf/buckets/response_buckets.c
index cb6a19c..d343a4c 100644
--- a/contrib/serf/buckets/response_buckets.c
+++ b/contrib/serf/buckets/response_buckets.c
@@ -19,7 +19,7 @@
#include "serf.h"
#include "serf_bucket_util.h"
-
+#include "serf_private.h"
typedef struct {
serf_bucket_t *stream;
diff --git a/contrib/serf/buckets/simple_buckets.c b/contrib/serf/buckets/simple_buckets.c
index f36239b..7ce7aeb 100644
--- a/contrib/serf/buckets/simple_buckets.c
+++ b/contrib/serf/buckets/simple_buckets.c
@@ -71,6 +71,23 @@ serf_bucket_t *serf_bucket_simple_copy_create(
return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
}
+serf_bucket_t *serf_bucket_simple_own_create(
+ const char *data, apr_size_t len,
+ serf_bucket_alloc_t *allocator)
+{
+ simple_context_t *ctx;
+
+ ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
+
+ ctx->original = ctx->current = data;
+
+ ctx->remaining = len;
+ ctx->freefunc = free_copied_data;
+ ctx->baton = allocator;
+
+ return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
+}
+
static apr_status_t serf_simple_read(serf_bucket_t *bucket,
apr_size_t requested,
const char **data, apr_size_t *len)
diff --git a/contrib/serf/buckets/ssl_buckets.c b/contrib/serf/buckets/ssl_buckets.c
index c5a0e60..d2ced94 100644
--- a/contrib/serf/buckets/ssl_buckets.c
+++ b/contrib/serf/buckets/ssl_buckets.c
@@ -211,14 +211,14 @@ apps_ssl_info_callback(const SSL *s, int where, int ret)
const char *str;
int w;
w = where & ~SSL_ST_MASK;
-
+
if (w & SSL_ST_CONNECT)
str = "SSL_connect";
else if (w & SSL_ST_ACCEPT)
str = "SSL_accept";
else
str = "undefined";
-
+
if (where & SSL_CB_LOOP) {
serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str,
SSL_state_string_long(s));
@@ -255,7 +255,8 @@ static int bio_bucket_read(BIO *bio, char *in, int inlen)
if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
&& BIO_should_read(ctx->bio)) {
- serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read waiting: (%d %d %d)\n",
+ serf__log(SSL_VERBOSE, __FILE__,
+ "bio_bucket_read waiting: (%d %d %d)\n",
BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
BIO_get_retry_flags(ctx->bio));
/* Falling back... */
@@ -296,7 +297,8 @@ static int bio_bucket_write(BIO *bio, const char *in, int inl)
if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
&& !BIO_should_read(ctx->bio)) {
- serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write waiting: (%d %d %d)\n",
+ serf__log(SSL_VERBOSE, __FILE__,
+ "bio_bucket_write waiting: (%d %d %d)\n",
BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
BIO_get_retry_flags(ctx->bio));
/* Falling back... */
@@ -570,6 +572,15 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
apr_pool_destroy(subpool);
}
+ /* Return a specific error if the server certificate is not accepted by
+ OpenSSL and the application has not set callbacks to override this. */
+ if (!cert_valid &&
+ !ctx->server_cert_chain_callback &&
+ !ctx->server_cert_callback)
+ {
+ ctx->pending_err = SERF_ERROR_SSL_CERT_FAILED;
+ }
+
return cert_valid;
}
@@ -621,9 +632,12 @@ static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
switch (ssl_err) {
case SSL_ERROR_SYSCALL:
*len = 0;
+ /* Return the underlying network error that caused OpenSSL
+ to fail. ### This can be a crypt error! */
status = ctx->decrypt.status;
break;
case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
*len = 0;
status = APR_EAGAIN;
break;
@@ -784,16 +798,19 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
serf__log(SSL_VERBOSE, __FILE__,
"ssl_encrypt: SSL write: %d\n", ssl_len);
- /* We're done. */
- serf_bucket_mem_free(ctx->allocator, vecs_data);
-
/* If we failed to write... */
if (ssl_len < 0) {
int ssl_err;
- /* Ah, bugger. We need to put that data back. */
- serf_bucket_aggregate_prepend_iovec(ctx->encrypt.stream,
- vecs, vecs_read);
+ /* Ah, bugger. We need to put that data back.
+ Note: use the copy here, we do not own the original iovec
+ data buffer so it will be freed on next read. */
+ serf_bucket_t *vecs_copy =
+ serf_bucket_simple_own_create(vecs_data,
+ vecs_data_len,
+ ctx->allocator);
+ serf_bucket_aggregate_prepend(ctx->encrypt.stream,
+ vecs_copy);
ssl_err = SSL_get_error(ctx->ssl, ssl_len);
@@ -801,6 +818,8 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
"ssl_encrypt: SSL write error: %d\n", ssl_err);
if (ssl_err == SSL_ERROR_SYSCALL) {
+ /* Return the underlying network error that caused OpenSSL
+ to fail. ### This can be a decrypt error! */
status = ctx->encrypt.status;
if (SERF_BUCKET_READ_ERROR(status)) {
return status;
@@ -812,13 +831,17 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
status = SERF_ERROR_WAIT_CONN;
}
else {
- ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
+ ctx->fatal_err = status =
+ SERF_ERROR_SSL_COMM_FAILED;
}
}
serf__log(SSL_VERBOSE, __FILE__,
"ssl_encrypt: SSL write error: %d %d\n",
status, *len);
+ } else {
+ /* We're done with this data. */
+ serf_bucket_mem_free(ctx->allocator, vecs_data);
}
}
}
@@ -1024,7 +1047,7 @@ static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
}
if (status || !cert_path) {
- break;
+ break;
}
/* Load the x.509 cert file stored in PKCS12 */
@@ -1313,7 +1336,7 @@ apr_status_t serf_ssl_load_cert_file(
apr_pool_t *pool)
{
FILE *fp = fopen(file_path, "r");
-
+
if (fp) {
X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
fclose(fp);
OpenPOWER on IntegriCloud