]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/serf/buckets/limit_buckets.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / serf / buckets / limit_buckets.c
1 /* Copyright 2002-2004 Justin Erenkrantz and Greg Stein
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <apr_pools.h>
17
18 #include "serf.h"
19 #include "serf_bucket_util.h"
20 #include "serf_private.h"
21
22 typedef struct {
23     serf_bucket_t *stream;
24     apr_uint64_t remaining;
25 } limit_context_t;
26
27
28 serf_bucket_t *serf_bucket_limit_create(
29     serf_bucket_t *stream, apr_uint64_t len, serf_bucket_alloc_t *allocator)
30 {
31     limit_context_t *ctx;
32
33     ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
34     ctx->stream = stream;
35     ctx->remaining = len;
36
37     return serf_bucket_create(&serf_bucket_type_limit, allocator, ctx);
38 }
39
40 static apr_status_t serf_limit_read(serf_bucket_t *bucket,
41                                     apr_size_t requested,
42                                     const char **data, apr_size_t *len)
43 {
44     limit_context_t *ctx = bucket->data;
45     apr_status_t status;
46
47     if (!ctx->remaining) {
48         *len = 0;
49         return APR_EOF;
50     }
51
52     if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining) {
53         if (ctx->remaining <= REQUESTED_MAX) {
54             requested = (apr_size_t) ctx->remaining;
55         } else {
56             requested = REQUESTED_MAX;
57         }
58     }
59
60     status = serf_bucket_read(ctx->stream, requested, data, len);
61
62     if (!SERF_BUCKET_READ_ERROR(status)) {
63         ctx->remaining -= *len;
64     }
65
66     /* If we have met our limit and don't have a status, return EOF. */
67     if (!ctx->remaining && !status) {
68         status = APR_EOF;
69     }
70
71     return status;
72 }
73
74 static apr_status_t serf_limit_readline(serf_bucket_t *bucket,
75                                          int acceptable, int *found,
76                                          const char **data, apr_size_t *len)
77 {
78     limit_context_t *ctx = bucket->data;
79     apr_status_t status;
80
81     if (!ctx->remaining) {
82         *len = 0;
83         return APR_EOF;
84     }
85
86     status = serf_bucket_readline(ctx->stream, acceptable, found, data, len);
87
88     if (!SERF_BUCKET_READ_ERROR(status)) {
89         ctx->remaining -= *len;
90     }
91
92     /* If we have met our limit and don't have a status, return EOF. */
93     if (!ctx->remaining && !status) {
94         status = APR_EOF;
95     }
96
97     return status;
98 }
99
100 static apr_status_t serf_limit_peek(serf_bucket_t *bucket,
101                                      const char **data,
102                                      apr_size_t *len)
103 {
104     limit_context_t *ctx = bucket->data;
105
106     return serf_bucket_peek(ctx->stream, data, len);
107 }
108
109 static void serf_limit_destroy(serf_bucket_t *bucket)
110 {
111     limit_context_t *ctx = bucket->data;
112
113     serf_bucket_destroy(ctx->stream);
114
115     serf_default_destroy_and_data(bucket);
116 }
117
118 const serf_bucket_type_t serf_bucket_type_limit = {
119     "LIMIT",
120     serf_limit_read,
121     serf_limit_readline,
122     serf_default_read_iovec,
123     serf_default_read_for_sendfile,
124     serf_default_read_bucket,
125     serf_limit_peek,
126     serf_limit_destroy,
127 };