diff options
author | Peter Wemm <peter@FreeBSD.org> | 2013-08-02 19:12:12 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 2013-08-02 19:12:12 +0000 |
commit | 1f89a666e3d8a4c37bde40615cdb08cad7fbd422 (patch) | |
tree | 1b30c737cff0d7cfa1fa6974ee527413d07377d8 /buckets | |
parent | 4e6fa1a5527bdafe16ff845932d9cdcf9c51d8f6 (diff) |
Import serf-1.3.0vendor/serf/serf-1.3.0
Notes
Notes:
svn path=/vendor/serf/dist/; revision=253893
svn path=/vendor/serf/serf-1.3.0/; revision=253894; tag=vendor/serf/serf-1.3.0
Diffstat (limited to 'buckets')
-rw-r--r-- | buckets/aggregate_buckets.c | 96 | ||||
-rw-r--r-- | buckets/buckets.c | 28 | ||||
-rw-r--r-- | buckets/dechunk_buckets.c | 4 | ||||
-rw-r--r-- | buckets/headers_buckets.c | 4 | ||||
-rw-r--r-- | buckets/limit_buckets.c | 9 | ||||
-rw-r--r-- | buckets/request_buckets.c | 11 | ||||
-rw-r--r-- | buckets/response_buckets.c | 2 | ||||
-rw-r--r-- | buckets/simple_buckets.c | 17 | ||||
-rw-r--r-- | buckets/ssl_buckets.c | 49 |
9 files changed, 184 insertions, 36 deletions
diff --git a/buckets/aggregate_buckets.c b/buckets/aggregate_buckets.c index d9d15a3d33e9..2ae3fd538b96 100644 --- a/buckets/aggregate_buckets.c +++ b/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/buckets/buckets.c b/buckets/buckets.c index 72b3913a32ea..88e256b8c7fd 100644 --- a/buckets/buckets.c +++ b/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/buckets/dechunk_buckets.c b/buckets/dechunk_buckets.c index 262cffbdaccd..eda1e22642a3 100644 --- a/buckets/dechunk_buckets.c +++ b/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/buckets/headers_buckets.c b/buckets/headers_buckets.c index 1c37ef045d3d..6401f7fc1df2 100644 --- a/buckets/headers_buckets.c +++ b/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/buckets/limit_buckets.c b/buckets/limit_buckets.c index d2e61665eb8a..70b7efb3d620 100644 --- a/buckets/limit_buckets.c +++ b/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/buckets/request_buckets.c b/buckets/request_buckets.c index be010c0acb81..912da8ad6df7 100644 --- a/buckets/request_buckets.c +++ b/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/buckets/response_buckets.c b/buckets/response_buckets.c index cb6a19cebe43..d343a4cb9a64 100644 --- a/buckets/response_buckets.c +++ b/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/buckets/simple_buckets.c b/buckets/simple_buckets.c index f36239bb5974..7ce7aeb25fd1 100644 --- a/buckets/simple_buckets.c +++ b/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/buckets/ssl_buckets.c b/buckets/ssl_buckets.c index c5a0e60e0f86..d2ced9449d4b 100644 --- a/buckets/ssl_buckets.c +++ b/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); |