xref: /trueos/contrib/serf/buckets/limit_buckets.c (revision 9394ef331eb7d0ba7f22583970cc84b62ad9f19a)
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 
serf_bucket_limit_create(serf_bucket_t * stream,apr_uint64_t len,serf_bucket_alloc_t * allocator)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 
serf_limit_read(serf_bucket_t * bucket,apr_size_t requested,const char ** data,apr_size_t * len)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 
serf_limit_readline(serf_bucket_t * bucket,int acceptable,int * found,const char ** data,apr_size_t * len)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 
serf_limit_peek(serf_bucket_t * bucket,const char ** data,apr_size_t * len)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 
serf_limit_destroy(serf_bucket_t * bucket)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 };
128