ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/vendor/serf/1.3.9/buckets/iovec_buckets.c
Revision: 9260
Committed: Mon Feb 20 02:15:06 2017 UTC (7 years, 2 months ago) by laffer1
Content type: text/plain
File size: 5250 byte(s)
Log Message:
serf 1.3.9

File Contents

# Content
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 struct iovec *vecs;
29
30 /* Total number of buffer stored in the vecs var. */
31 int vecs_len;
32 /* Points to the first unread buffer. */
33 int current_vec;
34 /* First buffer offset. */
35 int offset;
36 } iovec_context_t;
37
38 serf_bucket_t *serf_bucket_iovec_create(
39 struct iovec vecs[],
40 int len,
41 serf_bucket_alloc_t *allocator)
42 {
43 iovec_context_t *ctx;
44 int i;
45
46 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
47 ctx->vecs = serf_bucket_mem_alloc(allocator, len * sizeof(struct iovec));
48 ctx->vecs_len = len;
49 ctx->current_vec = 0;
50 ctx->offset = 0;
51
52 /* copy all buffers to our iovec. */
53 for (i = 0; i < len; i++) {
54 ctx->vecs[i].iov_base = vecs[i].iov_base;
55 ctx->vecs[i].iov_len = vecs[i].iov_len;
56 }
57
58 return serf_bucket_create(&serf_bucket_type_iovec, allocator, ctx);
59 }
60
61 static apr_status_t serf_iovec_readline(serf_bucket_t *bucket,
62 int acceptable, int *found,
63 const char **data, apr_size_t *len)
64 {
65 return APR_ENOTIMPL;
66 }
67
68 static apr_status_t serf_iovec_read_iovec(serf_bucket_t *bucket,
69 apr_size_t requested,
70 int vecs_size,
71 struct iovec *vecs,
72 int *vecs_used)
73 {
74 iovec_context_t *ctx = bucket->data;
75
76 *vecs_used = 0;
77
78 /* copy the requested amount of buffers to the provided iovec. */
79 for (; ctx->current_vec < ctx->vecs_len; ctx->current_vec++) {
80 struct iovec vec = ctx->vecs[ctx->current_vec];
81 apr_size_t remaining;
82
83 if (requested != SERF_READ_ALL_AVAIL && requested <= 0)
84 break;
85 if (*vecs_used >= vecs_size)
86 break;
87
88 vecs[*vecs_used].iov_base = (char*)vec.iov_base + ctx->offset;
89 remaining = vec.iov_len - ctx->offset;
90
91 /* Less bytes requested than remaining in the current buffer. */
92 if (requested != SERF_READ_ALL_AVAIL && requested < remaining) {
93 vecs[*vecs_used].iov_len = requested;
94 ctx->offset += requested;
95 requested = 0;
96 (*vecs_used)++;
97 break;
98 } else {
99 /* Copy the complete buffer. */
100 vecs[*vecs_used].iov_len = remaining;
101 ctx->offset = 0;
102 if (requested != SERF_READ_ALL_AVAIL)
103 requested -= remaining;
104 (*vecs_used)++;
105 }
106 }
107
108 if (ctx->current_vec == ctx->vecs_len && !ctx->offset)
109 return APR_EOF;
110
111 return APR_SUCCESS;
112 }
113
114 static apr_status_t serf_iovec_read(serf_bucket_t *bucket,
115 apr_size_t requested,
116 const char **data, apr_size_t *len)
117 {
118 struct iovec vec[1];
119 apr_status_t status;
120 int vecs_used;
121
122 status = serf_iovec_read_iovec(bucket, requested, 1, vec, &vecs_used);
123
124 if (vecs_used) {
125 *data = vec[0].iov_base;
126 *len = vec[0].iov_len;
127 } else {
128 *len = 0;
129 }
130
131 return status;
132 }
133
134 static apr_status_t serf_iovec_peek(serf_bucket_t *bucket,
135 const char **data,
136 apr_size_t *len)
137 {
138 iovec_context_t *ctx = bucket->data;
139
140 if (ctx->current_vec >= ctx->vecs_len) {
141 *len = 0;
142 return APR_EOF;
143 }
144
145 /* Return the first unread buffer, don't bother combining all
146 remaining data. */
147 *data = ctx->vecs[ctx->current_vec].iov_base;
148 *len = ctx->vecs[ctx->current_vec].iov_len;
149
150 if (ctx->current_vec + 1 == ctx->vecs_len)
151 return APR_EOF;
152
153 return APR_SUCCESS;
154 }
155
156 static void serf_iovec_destroy(serf_bucket_t *bucket)
157 {
158 iovec_context_t *ctx = bucket->data;
159
160 serf_bucket_mem_free(bucket->allocator, ctx->vecs);
161 serf_default_destroy_and_data(bucket);
162 }
163
164
165 const serf_bucket_type_t serf_bucket_type_iovec = {
166 "IOVEC",
167 serf_iovec_read,
168 serf_iovec_readline,
169 serf_iovec_read_iovec,
170 serf_default_read_for_sendfile,
171 serf_default_read_bucket,
172 serf_iovec_peek,
173 serf_iovec_destroy,
174 };