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
convert_error(quicly_stream_t * stream,int err)27 static void convert_error(quicly_stream_t *stream, int err)
28 {
29 assert(err != 0);
30 if (QUICLY_ERROR_IS_QUIC_APPLICATION(err)) {
31 if (quicly_stream_has_send_side(quicly_is_client(stream->conn), stream->stream_id) &&
32 quicly_sendstate_is_open(&stream->sendstate))
33 quicly_reset_stream(stream, err);
34 if (quicly_stream_has_receive_side(quicly_is_client(stream->conn), stream->stream_id))
35 quicly_request_stop(stream, err);
36 } else {
37 quicly_close(stream->conn, QUICLY_ERROR_IS_QUIC_TRANSPORT(err) ? err : QUICLY_TRANSPORT_ERROR_INTERNAL, NULL);
38 }
39 }
40
quicly_sendbuf_dispose(quicly_sendbuf_t * sb)41 void quicly_sendbuf_dispose(quicly_sendbuf_t *sb)
42 {
43 size_t i;
44
45 for (i = 0; i != sb->vecs.size; ++i) {
46 quicly_sendbuf_vec_t *vec = sb->vecs.entries + i;
47 if (vec->cb->discard_vec != NULL)
48 vec->cb->discard_vec(vec);
49 }
50 free(sb->vecs.entries);
51 }
52
quicly_sendbuf_shift(quicly_stream_t * stream,quicly_sendbuf_t * sb,size_t delta)53 void quicly_sendbuf_shift(quicly_stream_t *stream, quicly_sendbuf_t *sb, size_t delta)
54 {
55 size_t i;
56
57 for (i = 0; delta != 0; ++i) {
58 assert(i < sb->vecs.size);
59 quicly_sendbuf_vec_t *first_vec = sb->vecs.entries + i;
60 size_t bytes_in_first_vec = first_vec->len - sb->off_in_first_vec;
61 if (delta < bytes_in_first_vec) {
62 sb->off_in_first_vec += delta;
63 break;
64 }
65 delta -= bytes_in_first_vec;
66 if (first_vec->cb->discard_vec != NULL)
67 first_vec->cb->discard_vec(first_vec);
68 sb->off_in_first_vec = 0;
69 }
70 if (i != 0) {
71 if (sb->vecs.size != i) {
72 memmove(sb->vecs.entries, sb->vecs.entries + i, (sb->vecs.size - i) * sizeof(*sb->vecs.entries));
73 sb->vecs.size -= i;
74 } else {
75 free(sb->vecs.entries);
76 sb->vecs.entries = NULL;
77 sb->vecs.size = 0;
78 sb->vecs.capacity = 0;
79 }
80 }
81 quicly_stream_sync_sendbuf(stream, 0);
82 }
83
quicly_sendbuf_emit(quicly_stream_t * stream,quicly_sendbuf_t * sb,size_t off,void * dst,size_t * len,int * wrote_all)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 {
86 size_t vec_index, capacity = *len;
87 int ret;
88
89 off += sb->off_in_first_vec;
90 for (vec_index = 0; capacity != 0 && vec_index < sb->vecs.size; ++vec_index) {
91 quicly_sendbuf_vec_t *vec = sb->vecs.entries + vec_index;
92 if (off < vec->len) {
93 size_t bytes_flatten = vec->len - off;
94 int partial = 0;
95 if (capacity < bytes_flatten) {
96 bytes_flatten = capacity;
97 partial = 1;
98 }
99 if ((ret = vec->cb->flatten_vec(vec, dst, off, bytes_flatten)) != 0) {
100 convert_error(stream, ret);
101 return;
102 }
103 dst = (uint8_t *)dst + bytes_flatten;
104 capacity -= bytes_flatten;
105 off = 0;
106 if (partial)
107 break;
108 } else {
109 off -= vec->len;
110 }
111 }
112
113 if (capacity == 0 && vec_index < sb->vecs.size) {
114 *wrote_all = 0;
115 } else {
116 *len = *len - capacity;
117 *wrote_all = 1;
118 }
119 }
120
flatten_raw(quicly_sendbuf_vec_t * vec,void * dst,size_t off,size_t len)121 static int flatten_raw(quicly_sendbuf_vec_t *vec, void *dst, size_t off, size_t len)
122 {
123 memcpy(dst, (uint8_t *)vec->cbdata + off, len);
124 return 0;
125 }
126
discard_raw(quicly_sendbuf_vec_t * vec)127 static void discard_raw(quicly_sendbuf_vec_t *vec)
128 {
129 free(vec->cbdata);
130 }
131
quicly_sendbuf_write(quicly_stream_t * stream,quicly_sendbuf_t * sb,const void * src,size_t len)132 int quicly_sendbuf_write(quicly_stream_t *stream, quicly_sendbuf_t *sb, const void *src, size_t len)
133 {
134 static const quicly_streambuf_sendvec_callbacks_t raw_callbacks = {flatten_raw, discard_raw};
135 quicly_sendbuf_vec_t vec = {&raw_callbacks, len, NULL};
136 int ret;
137
138 assert(quicly_sendstate_is_open(&stream->sendstate));
139
140 if ((vec.cbdata = malloc(len)) == NULL) {
141 ret = PTLS_ERROR_NO_MEMORY;
142 goto Error;
143 }
144 memcpy(vec.cbdata, src, len);
145 if ((ret = quicly_sendbuf_write_vec(stream, sb, &vec)) != 0)
146 goto Error;
147 return 0;
148
149 Error:
150 free(vec.cbdata);
151 return ret;
152 }
153
quicly_sendbuf_write_vec(quicly_stream_t * stream,quicly_sendbuf_t * sb,quicly_sendbuf_vec_t * vec)154 int quicly_sendbuf_write_vec(quicly_stream_t *stream, quicly_sendbuf_t *sb, quicly_sendbuf_vec_t *vec)
155 {
156 assert(sb->vecs.size <= sb->vecs.capacity);
157
158 if (sb->vecs.size == sb->vecs.capacity) {
159 quicly_sendbuf_vec_t *new_entries;
160 size_t new_capacity = sb->vecs.capacity == 0 ? 4 : sb->vecs.capacity * 2;
161 if ((new_entries = realloc(sb->vecs.entries, new_capacity * sizeof(*sb->vecs.entries))) == NULL)
162 return PTLS_ERROR_NO_MEMORY;
163 sb->vecs.entries = new_entries;
164 sb->vecs.capacity = new_capacity;
165 }
166 sb->vecs.entries[sb->vecs.size++] = *vec;
167 sb->bytes_written += vec->len;
168
169 return quicly_stream_sync_sendbuf(stream, 1);
170 }
171
quicly_recvbuf_shift(quicly_stream_t * stream,ptls_buffer_t * rb,size_t delta)172 void quicly_recvbuf_shift(quicly_stream_t *stream, ptls_buffer_t *rb, size_t delta)
173 {
174 assert(delta <= rb->off);
175 rb->off -= delta;
176 memmove(rb->base, rb->base + delta, rb->off);
177
178 quicly_stream_sync_recvbuf(stream, delta);
179 }
180
quicly_recvbuf_get(quicly_stream_t * stream,ptls_buffer_t * rb)181 ptls_iovec_t quicly_recvbuf_get(quicly_stream_t *stream, ptls_buffer_t *rb)
182 {
183 size_t avail;
184
185 if (quicly_recvstate_transfer_complete(&stream->recvstate)) {
186 avail = rb->off;
187 } else if (stream->recvstate.data_off < stream->recvstate.received.ranges[0].end) {
188 avail = stream->recvstate.received.ranges[0].end - stream->recvstate.data_off;
189 } else {
190 avail = 0;
191 }
192
193 return ptls_iovec_init(rb->base, avail);
194 }
195
quicly_recvbuf_receive(quicly_stream_t * stream,ptls_buffer_t * rb,size_t off,const void * src,size_t len)196 int quicly_recvbuf_receive(quicly_stream_t *stream, ptls_buffer_t *rb, size_t off, const void *src, size_t len)
197 {
198 if (len != 0) {
199 int ret;
200 if ((ret = ptls_buffer_reserve(rb, off + len - rb->off)) != 0) {
201 convert_error(stream, ret);
202 return -1;
203 }
204 memcpy(rb->base + off, src, len);
205 if (rb->off < off + len)
206 rb->off = off + len;
207 }
208 return 0;
209 }
210
quicly_streambuf_create(quicly_stream_t * stream,size_t sz)211 int quicly_streambuf_create(quicly_stream_t *stream, size_t sz)
212 {
213 quicly_streambuf_t *sbuf;
214
215 assert(sz >= sizeof(*sbuf));
216 assert(stream->data == NULL);
217
218 if ((sbuf = malloc(sz)) == NULL)
219 return PTLS_ERROR_NO_MEMORY;
220 quicly_sendbuf_init(&sbuf->egress);
221 ptls_buffer_init(&sbuf->ingress, "", 0);
222 if (sz != sizeof(*sbuf))
223 memset((char *)sbuf + sizeof(*sbuf), 0, sz - sizeof(*sbuf));
224
225 stream->data = sbuf;
226 return 0;
227 }
228
quicly_streambuf_destroy(quicly_stream_t * stream,int err)229 void quicly_streambuf_destroy(quicly_stream_t *stream, int err)
230 {
231 quicly_streambuf_t *sbuf = stream->data;
232
233 quicly_sendbuf_dispose(&sbuf->egress);
234 ptls_buffer_dispose(&sbuf->ingress);
235 free(sbuf);
236 stream->data = NULL;
237 }
238
quicly_streambuf_egress_emit(quicly_stream_t * stream,size_t off,void * dst,size_t * len,int * wrote_all)239 void quicly_streambuf_egress_emit(quicly_stream_t *stream, size_t off, void *dst, size_t *len, int *wrote_all)
240 {
241 quicly_streambuf_t *sbuf = stream->data;
242 quicly_sendbuf_emit(stream, &sbuf->egress, off, dst, len, wrote_all);
243 }
244
quicly_streambuf_egress_shutdown(quicly_stream_t * stream)245 int quicly_streambuf_egress_shutdown(quicly_stream_t *stream)
246 {
247 quicly_streambuf_t *sbuf = stream->data;
248 quicly_sendstate_shutdown(&stream->sendstate, sbuf->egress.bytes_written);
249 return quicly_stream_sync_sendbuf(stream, 1);
250 }
251
quicly_streambuf_ingress_receive(quicly_stream_t * stream,size_t off,const void * src,size_t len)252 int quicly_streambuf_ingress_receive(quicly_stream_t *stream, size_t off, const void *src, size_t len)
253 {
254 quicly_streambuf_t *sbuf = stream->data;
255 return quicly_recvbuf_receive(stream, &sbuf->ingress, off, src, len);
256 }
257