limit_buckets.c revision 251877
1193323Sed/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein 2193323Sed * 3193323Sed * Licensed under the Apache License, Version 2.0 (the "License"); 4193323Sed * you may not use this file except in compliance with the License. 5193323Sed * You may obtain a copy of the License at 6193323Sed * 7193323Sed * http://www.apache.org/licenses/LICENSE-2.0 8193323Sed * 9193323Sed * Unless required by applicable law or agreed to in writing, software 10193323Sed * distributed under the License is distributed on an "AS IS" BASIS, 11193323Sed * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12193323Sed * See the License for the specific language governing permissions and 13193323Sed * limitations under the License. 14193323Sed */ 15193323Sed 16193323Sed#include <apr_pools.h> 17193323Sed 18249423Sdim#include "serf.h" 19249423Sdim#include "serf_bucket_util.h" 20193323Sed 21198090Srdivacky/* Older versions of APR do not have this macro. */ 22198090Srdivacky#ifdef APR_SIZE_MAX 23193323Sed#define REQUESTED_MAX APR_SIZE_MAX 24193323Sed#else 25193323Sed#define REQUESTED_MAX (~((apr_size_t)0)) 26193323Sed#endif 27193323Sed 28193323Sed 29193323Sedtypedef struct { 30193323Sed serf_bucket_t *stream; 31193323Sed apr_uint64_t remaining; 32193323Sed} limit_context_t; 33193323Sed 34193323Sed 35193323Sedserf_bucket_t *serf_bucket_limit_create( 36193323Sed serf_bucket_t *stream, apr_uint64_t len, serf_bucket_alloc_t *allocator) 37193323Sed{ 38193323Sed limit_context_t *ctx; 39193323Sed 40193323Sed ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 41193323Sed ctx->stream = stream; 42193323Sed ctx->remaining = len; 43193323Sed 44193323Sed return serf_bucket_create(&serf_bucket_type_limit, allocator, ctx); 45193323Sed} 46193323Sed 47193323Sedstatic apr_status_t serf_limit_read(serf_bucket_t *bucket, 48193323Sed apr_size_t requested, 49193323Sed const char **data, apr_size_t *len) 50193323Sed{ 51193323Sed limit_context_t *ctx = bucket->data; 52193323Sed apr_status_t status; 53193323Sed 54193323Sed if (!ctx->remaining) { 55193323Sed *len = 0; 56193323Sed return APR_EOF; 57193323Sed } 58193323Sed 59193323Sed if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining) { 60193323Sed if (ctx->remaining <= REQUESTED_MAX) { 61193323Sed requested = (apr_size_t) ctx->remaining; 62193323Sed } else { 63193323Sed requested = REQUESTED_MAX; 64193323Sed } 65193323Sed } 66193323Sed 67199989Srdivacky status = serf_bucket_read(ctx->stream, requested, data, len); 68199989Srdivacky 69199989Srdivacky if (!SERF_BUCKET_READ_ERROR(status)) { 70199989Srdivacky ctx->remaining -= *len; 71199989Srdivacky } 72199989Srdivacky 73193323Sed /* If we have met our limit and don't have a status, return EOF. */ 74193323Sed if (!ctx->remaining && !status) { 75193323Sed status = APR_EOF; 76193323Sed } 77193323Sed 78193323Sed return status; 79193323Sed} 80193323Sed 81193323Sedstatic apr_status_t serf_limit_readline(serf_bucket_t *bucket, 82193323Sed int acceptable, int *found, 83193323Sed const char **data, apr_size_t *len) 84193323Sed{ 85193323Sed limit_context_t *ctx = bucket->data; 86193323Sed apr_status_t status; 87193323Sed 88193323Sed if (!ctx->remaining) { 89193323Sed *len = 0; 90193323Sed return APR_EOF; 91193323Sed } 92193323Sed 93193323Sed status = serf_bucket_readline(ctx->stream, acceptable, found, data, len); 94193323Sed 95193323Sed if (!SERF_BUCKET_READ_ERROR(status)) { 96193323Sed ctx->remaining -= *len; 97193323Sed } 98193323Sed 99193323Sed /* If we have met our limit and don't have a status, return EOF. */ 100193323Sed if (!ctx->remaining && !status) { 101193323Sed status = APR_EOF; 102193323Sed } 103193323Sed 104193323Sed return status; 105193323Sed} 106193323Sed 107193323Sedstatic apr_status_t serf_limit_peek(serf_bucket_t *bucket, 108193323Sed const char **data, 109193323Sed apr_size_t *len) 110193323Sed{ 111193323Sed limit_context_t *ctx = bucket->data; 112193323Sed 113193323Sed return serf_bucket_peek(ctx->stream, data, len); 114193323Sed} 115193323Sed 116193323Sedstatic void serf_limit_destroy(serf_bucket_t *bucket) 117193323Sed{ 118193323Sed limit_context_t *ctx = bucket->data; 119193323Sed 120193323Sed serf_bucket_destroy(ctx->stream); 121199989Srdivacky 122199989Srdivacky serf_default_destroy_and_data(bucket); 123199989Srdivacky} 124199989Srdivacky 125199989Srdivackyconst serf_bucket_type_t serf_bucket_type_limit = { 126202375Srdivacky "LIMIT", 127193323Sed serf_limit_read, 128193323Sed serf_limit_readline, 129193323Sed serf_default_read_iovec, 130193323Sed serf_default_read_for_sendfile, 131202375Srdivacky serf_default_read_bucket, 132193323Sed serf_limit_peek, 133193323Sed serf_limit_destroy, 134193323Sed}; 135193323Sed