1 /* ====================================================================
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 * ====================================================================
19 */
20
21 #include <apr_pools.h>
22
23 #include "serf.h"
24 #include "serf_bucket_util.h"
25
26
27 typedef struct {
28 const char *original;
29 const char *current;
30 apr_size_t remaining;
31
32 serf_simple_freefunc_t freefunc;
33 void *baton;
34
35 } simple_context_t;
36
37
free_copied_data(void * baton,const char * data)38 static void free_copied_data(void *baton, const char *data)
39 {
40 serf_bucket_mem_free(baton, (char*)data);
41 }
42
serf_bucket_simple_create(const char * data,apr_size_t len,serf_simple_freefunc_t freefunc,void * freefunc_baton,serf_bucket_alloc_t * allocator)43 serf_bucket_t *serf_bucket_simple_create(
44 const char *data,
45 apr_size_t len,
46 serf_simple_freefunc_t freefunc,
47 void *freefunc_baton,
48 serf_bucket_alloc_t *allocator)
49 {
50 simple_context_t *ctx;
51
52 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
53 ctx->original = ctx->current = data;
54 ctx->remaining = len;
55 ctx->freefunc = freefunc;
56 ctx->baton = freefunc_baton;
57
58 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
59 }
60
serf_bucket_simple_copy_create(const char * data,apr_size_t len,serf_bucket_alloc_t * allocator)61 serf_bucket_t *serf_bucket_simple_copy_create(
62 const char *data, apr_size_t len,
63 serf_bucket_alloc_t *allocator)
64 {
65 simple_context_t *ctx;
66
67 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
68
69 ctx->original = ctx->current = serf_bucket_mem_alloc(allocator, len);
70 memcpy((char*)ctx->original, data, len);
71
72 ctx->remaining = len;
73 ctx->freefunc = free_copied_data;
74 ctx->baton = allocator;
75
76 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
77 }
78
serf_bucket_simple_own_create(const char * data,apr_size_t len,serf_bucket_alloc_t * allocator)79 serf_bucket_t *serf_bucket_simple_own_create(
80 const char *data, apr_size_t len,
81 serf_bucket_alloc_t *allocator)
82 {
83 simple_context_t *ctx;
84
85 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
86
87 ctx->original = ctx->current = data;
88
89 ctx->remaining = len;
90 ctx->freefunc = free_copied_data;
91 ctx->baton = allocator;
92
93 return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
94 }
95
serf_simple_read(serf_bucket_t * bucket,apr_size_t requested,const char ** data,apr_size_t * len)96 static apr_status_t serf_simple_read(serf_bucket_t *bucket,
97 apr_size_t requested,
98 const char **data, apr_size_t *len)
99 {
100 simple_context_t *ctx = bucket->data;
101
102 if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining)
103 requested = ctx->remaining;
104
105 *data = ctx->current;
106 *len = requested;
107
108 ctx->current += requested;
109 ctx->remaining -= requested;
110
111 return ctx->remaining ? APR_SUCCESS : APR_EOF;
112 }
113
serf_simple_readline(serf_bucket_t * bucket,int acceptable,int * found,const char ** data,apr_size_t * len)114 static apr_status_t serf_simple_readline(serf_bucket_t *bucket,
115 int acceptable, int *found,
116 const char **data, apr_size_t *len)
117 {
118 simple_context_t *ctx = bucket->data;
119
120 /* Returned data will be from current position. */
121 *data = ctx->current;
122 serf_util_readline(&ctx->current, &ctx->remaining, acceptable, found);
123
124 /* See how much ctx->current moved forward. */
125 *len = ctx->current - *data;
126
127 return ctx->remaining ? APR_SUCCESS : APR_EOF;
128 }
129
serf_simple_peek(serf_bucket_t * bucket,const char ** data,apr_size_t * len)130 static apr_status_t serf_simple_peek(serf_bucket_t *bucket,
131 const char **data,
132 apr_size_t *len)
133 {
134 simple_context_t *ctx = bucket->data;
135
136 /* return whatever we have left */
137 *data = ctx->current;
138 *len = ctx->remaining;
139
140 /* we returned everything this bucket will ever hold */
141 return APR_EOF;
142 }
143
serf_simple_destroy(serf_bucket_t * bucket)144 static void serf_simple_destroy(serf_bucket_t *bucket)
145 {
146 simple_context_t *ctx = bucket->data;
147
148 if (ctx->freefunc)
149 (*ctx->freefunc)(ctx->baton, ctx->original);
150
151 serf_default_destroy_and_data(bucket);
152 }
153
154
155 const serf_bucket_type_t serf_bucket_type_simple = {
156 "SIMPLE",
157 serf_simple_read,
158 serf_simple_readline,
159 serf_default_read_iovec,
160 serf_default_read_for_sendfile,
161 serf_default_read_bucket,
162 serf_simple_peek,
163 serf_simple_destroy,
164 };
165