~ubuntu-branches/ubuntu/trusty/serf/trusty-security

« back to all changes in this revision

Viewing changes to buckets/iovec_buckets.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Samuelson
  • Date: 2011-06-27 18:09:28 UTC
  • mfrom: (1.2.5 upstream)
  • mto: (3.3.1 sid)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: james.westby@ubuntu.com-20110627180928-ybwzd3hmx82nu3ir
Tags: 1.0.0~0+svn1514-1
* New upstream snapshot.
  - patches/abi-0.x: Remove as obsolete.
  - patches/kqueue: Forward-port.
  - Bump ABI: libserf0.7{,-dbg} -> libserf1{,-dbg}
  - patches/ip6-localhost: New patch: temporary (I hope) workaround for
    IPv4 / IPv6 confusion in testsuite.
* Implement Multi-Arch: same.
* libserf-dev Conflicts: libserf-0-0-dev, not Breaks.  Thanks, lintian.

Show diffs side-by-side

added added

removed removed

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