Coverage Report

Created: 2023-06-07 06:21

/src/h2o/deps/quicly/lib/streambuf.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2018 Fastly, Kazuho Oku
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to
6
 * deal in the Software without restriction, including without limitation the
7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
 * sell copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
 * IN THE SOFTWARE.
21
 */
22
#include <assert.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include "quicly/streambuf.h"
26
27
static void convert_error(quicly_stream_t *stream, int err)
28
0
{
29
0
    assert(err != 0);
30
0
    if (QUICLY_ERROR_IS_QUIC_APPLICATION(err)) {
31
0
        if (quicly_stream_has_send_side(quicly_is_client(stream->conn), stream->stream_id) &&
32
0
            quicly_sendstate_is_open(&stream->sendstate))
33
0
            quicly_reset_stream(stream, err);
34
0
        if (quicly_stream_has_receive_side(quicly_is_client(stream->conn), stream->stream_id))
35
0
            quicly_request_stop(stream, err);
36
0
    } else {
37
0
        quicly_close(stream->conn, QUICLY_ERROR_IS_QUIC_TRANSPORT(err) ? err : QUICLY_TRANSPORT_ERROR_INTERNAL, NULL);
38
0
    }
39
0
}
40
41
void quicly_sendbuf_dispose(quicly_sendbuf_t *sb)
42
0
{
43
0
    size_t i;
44
45
0
    for (i = 0; i != sb->vecs.size; ++i) {
46
0
        quicly_sendbuf_vec_t *vec = sb->vecs.entries + i;
47
0
        if (vec->cb->discard_vec != NULL)
48
0
            vec->cb->discard_vec(vec);
49
0
    }
50
0
    free(sb->vecs.entries);
51
0
}
52
53
void quicly_sendbuf_shift(quicly_stream_t *stream, quicly_sendbuf_t *sb, size_t delta)
54
0
{
55
0
    size_t i;
56
57
0
    for (i = 0; delta != 0; ++i) {
58
0
        assert(i < sb->vecs.size);
59
0
        quicly_sendbuf_vec_t *first_vec = sb->vecs.entries + i;
60
0
        size_t bytes_in_first_vec = first_vec->len - sb->off_in_first_vec;
61
0
        if (delta < bytes_in_first_vec) {
62
0
            sb->off_in_first_vec += delta;
63
0
            break;
64
0
        }
65
0
        delta -= bytes_in_first_vec;
66
0
        if (first_vec->cb->discard_vec != NULL)
67
0
            first_vec->cb->discard_vec(first_vec);
68
0
        sb->off_in_first_vec = 0;
69
0
    }
70
0
    if (i != 0) {
71
0
        if (sb->vecs.size != i) {
72
0
            memmove(sb->vecs.entries, sb->vecs.entries + i, (sb->vecs.size - i) * sizeof(*sb->vecs.entries));
73
0
            sb->vecs.size -= i;
74
0
        } else {
75
0
            free(sb->vecs.entries);
76
0
            sb->vecs.entries = NULL;
77
0
            sb->vecs.size = 0;
78
0
            sb->vecs.capacity = 0;
79
0
        }
80
0
    }
81
0
    quicly_stream_sync_sendbuf(stream, 0);
82
0
}
83
84
void quicly_sendbuf_emit(quicly_stream_t *stream, quicly_sendbuf_t *sb, size_t off, void *dst, size_t *len, int *wrote_all)
85
0
{
86
0
    size_t vec_index, capacity = *len;
87
0
    int ret;
88
89
0
    off += sb->off_in_first_vec;
90
0
    for (vec_index = 0; capacity != 0 && vec_index < sb->vecs.size; ++vec_index) {
91
0
        quicly_sendbuf_vec_t *vec = sb->vecs.entries + vec_index;
92
0
        if (off < vec->len) {
93
0
            size_t bytes_flatten = vec->len - off;
94
0
            int partial = 0;
95
0
            if (capacity < bytes_flatten) {
96
0
                bytes_flatten = capacity;
97
0
                partial = 1;
98
0
            }
99
0
            if ((ret = vec->cb->flatten_vec(vec, dst, off, bytes_flatten)) != 0) {
100
0
                convert_error(stream, ret);
101
0
                return;
102
0
            }
103
0
            dst = (uint8_t *)dst + bytes_flatten;
104
0
            capacity -= bytes_flatten;
105
0
            off = 0;
106
0
            if (partial)
107
0
                break;
108
0
        } else {
109
0
            off -= vec->len;
110
0
        }
111
0
    }
112
113
0
    if (capacity == 0 && vec_index < sb->vecs.size) {
114
0
        *wrote_all = 0;
115
0
    } else {
116
0
        *len = *len - capacity;
117
0
        *wrote_all = 1;
118
0
    }
119
0
}
120
121
static int flatten_raw(quicly_sendbuf_vec_t *vec, void *dst, size_t off, size_t len)
122
0
{
123
0
    memcpy(dst, (uint8_t *)vec->cbdata + off, len);
124
0
    return 0;
125
0
}
126
127
static void discard_raw(quicly_sendbuf_vec_t *vec)
128
0
{
129
0
    free(vec->cbdata);
130
0
}
131
132
int quicly_sendbuf_write(quicly_stream_t *stream, quicly_sendbuf_t *sb, const void *src, size_t len)
133
0
{
134
0
    static const quicly_streambuf_sendvec_callbacks_t raw_callbacks = {flatten_raw, discard_raw};
135
0
    quicly_sendbuf_vec_t vec = {&raw_callbacks, len, NULL};
136
0
    int ret;
137
138
0
    assert(quicly_sendstate_is_open(&stream->sendstate));
139
140
0
    if ((vec.cbdata = malloc(len)) == NULL) {
141
0
        ret = PTLS_ERROR_NO_MEMORY;
142
0
        goto Error;
143
0
    }
144
0
    memcpy(vec.cbdata, src, len);
145
0
    if ((ret = quicly_sendbuf_write_vec(stream, sb, &vec)) != 0)
146
0
        goto Error;
147
0
    return 0;
148
149
0
Error:
150
0
    free(vec.cbdata);
151
0
    return ret;
152
0
}
153
154
int quicly_sendbuf_write_vec(quicly_stream_t *stream, quicly_sendbuf_t *sb, quicly_sendbuf_vec_t *vec)
155
0
{
156
0
    assert(sb->vecs.size <= sb->vecs.capacity);
157
158
0
    if (sb->vecs.size == sb->vecs.capacity) {
159
0
        quicly_sendbuf_vec_t *new_entries;
160
0
        size_t new_capacity = sb->vecs.capacity == 0 ? 4 : sb->vecs.capacity * 2;
161
0
        if ((new_entries = realloc(sb->vecs.entries, new_capacity * sizeof(*sb->vecs.entries))) == NULL)
162
0
            return PTLS_ERROR_NO_MEMORY;
163
0
        sb->vecs.entries = new_entries;
164
0
        sb->vecs.capacity = new_capacity;
165
0
    }
166
0
    sb->vecs.entries[sb->vecs.size++] = *vec;
167
0
    sb->bytes_written += vec->len;
168
169
0
    return quicly_stream_sync_sendbuf(stream, 1);
170
0
}
171
172
void quicly_recvbuf_shift(quicly_stream_t *stream, ptls_buffer_t *rb, size_t delta)
173
0
{
174
0
    assert(delta <= rb->off);
175
0
    rb->off -= delta;
176
0
    memmove(rb->base, rb->base + delta, rb->off);
177
178
0
    quicly_stream_sync_recvbuf(stream, delta);
179
0
}
180
181
ptls_iovec_t quicly_recvbuf_get(quicly_stream_t *stream, ptls_buffer_t *rb)
182
0
{
183
0
    size_t avail;
184
185
0
    if (quicly_recvstate_transfer_complete(&stream->recvstate)) {
186
0
        avail = rb->off;
187
0
    } else if (stream->recvstate.data_off < stream->recvstate.received.ranges[0].end) {
188
0
        avail = stream->recvstate.received.ranges[0].end - stream->recvstate.data_off;
189
0
    } else {
190
0
        avail = 0;
191
0
    }
192
193
0
    return ptls_iovec_init(rb->base, avail);
194
0
}
195
196
int quicly_recvbuf_receive(quicly_stream_t *stream, ptls_buffer_t *rb, size_t off, const void *src, size_t len)
197
0
{
198
0
    if (len != 0) {
199
0
        int ret;
200
0
        if ((ret = ptls_buffer_reserve(rb, off + len - rb->off)) != 0) {
201
0
            convert_error(stream, ret);
202
0
            return -1;
203
0
        }
204
0
        memcpy(rb->base + off, src, len);
205
0
        if (rb->off < off + len)
206
0
            rb->off = off + len;
207
0
    }
208
0
    return 0;
209
0
}
210
211
int quicly_streambuf_create(quicly_stream_t *stream, size_t sz)
212
0
{
213
0
    quicly_streambuf_t *sbuf;
214
215
0
    assert(sz >= sizeof(*sbuf));
216
0
    assert(stream->data == NULL);
217
218
0
    if ((sbuf = malloc(sz)) == NULL)
219
0
        return PTLS_ERROR_NO_MEMORY;
220
0
    quicly_sendbuf_init(&sbuf->egress);
221
0
    ptls_buffer_init(&sbuf->ingress, "", 0);
222
0
    if (sz != sizeof(*sbuf))
223
0
        memset((char *)sbuf + sizeof(*sbuf), 0, sz - sizeof(*sbuf));
224
225
0
    stream->data = sbuf;
226
0
    return 0;
227
0
}
228
229
void quicly_streambuf_destroy(quicly_stream_t *stream, int err)
230
0
{
231
0
    quicly_streambuf_t *sbuf = stream->data;
232
233
0
    quicly_sendbuf_dispose(&sbuf->egress);
234
0
    ptls_buffer_dispose(&sbuf->ingress);
235
0
    free(sbuf);
236
0
    stream->data = NULL;
237
0
}
238
239
void quicly_streambuf_egress_emit(quicly_stream_t *stream, size_t off, void *dst, size_t *len, int *wrote_all)
240
0
{
241
0
    quicly_streambuf_t *sbuf = stream->data;
242
0
    quicly_sendbuf_emit(stream, &sbuf->egress, off, dst, len, wrote_all);
243
0
}
244
245
int quicly_streambuf_egress_shutdown(quicly_stream_t *stream)
246
0
{
247
0
    quicly_streambuf_t *sbuf = stream->data;
248
0
    quicly_sendstate_shutdown(&stream->sendstate, sbuf->egress.bytes_written);
249
0
    return quicly_stream_sync_sendbuf(stream, 1);
250
0
}
251
252
int quicly_streambuf_ingress_receive(quicly_stream_t *stream, size_t off, const void *src, size_t len)
253
0
{
254
0
    quicly_streambuf_t *sbuf = stream->data;
255
0
    return quicly_recvbuf_receive(stream, &sbuf->ingress, off, src, len);
256
0
}