1 /* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
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
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <http_core.h>
21 #include <http_connection.h>
23 #include "h2_private.h"
25 #include "h2_response.h"
29 h2_io *h2_io_create(int id, apr_pool_t *pool, apr_bucket_alloc_t *bucket_alloc)
31 h2_io *io = apr_pcalloc(pool, sizeof(*io));
36 io->bbout = apr_brigade_create(pool, bucket_alloc);
41 static void h2_io_cleanup(h2_io *io)
44 h2_task_destroy(io->task);
49 void h2_io_destroy(h2_io *io)
54 void h2_io_set_response(h2_io *io, h2_response *response)
56 AP_DEBUG_ASSERT(response);
57 AP_DEBUG_ASSERT(!io->response);
58 io->response = h2_response_copy(io->pool, response);
59 if (response->rst_error) {
60 h2_io_rst(io, response->rst_error);
65 void h2_io_rst(h2_io *io, int error)
67 io->rst_error = error;
71 int h2_io_in_has_eos_for(h2_io *io)
73 return io->eos_in || (io->bbin && h2_util_has_eos(io->bbin, 0));
76 int h2_io_out_has_data(h2_io *io)
78 return h2_util_bb_has_data_or_eos(io->bbout);
81 apr_size_t h2_io_out_length(h2_io *io)
85 apr_brigade_length(io->bbout, 0, &len);
86 return (len > 0)? len : 0;
91 apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb,
94 apr_off_t start_len = 0;
99 return APR_ECONNABORTED;
102 if (!io->bbin || APR_BRIGADE_EMPTY(io->bbin)) {
103 return io->eos_in? APR_EOF : APR_EAGAIN;
106 apr_brigade_length(bb, 1, &start_len);
107 last = APR_BRIGADE_LAST(bb);
108 status = h2_util_move(bb, io->bbin, maxlen, NULL, "h2_io_in_read");
109 if (status == APR_SUCCESS) {
110 apr_bucket *nlast = APR_BRIGADE_LAST(bb);
111 apr_off_t end_len = 0;
112 apr_brigade_length(bb, 1, &end_len);
116 io->input_consumed += (end_len - start_len);
121 apr_status_t h2_io_in_write(h2_io *io, apr_bucket_brigade *bb)
124 return APR_ECONNABORTED;
130 io->eos_in = h2_util_has_eos(bb, 0);
131 if (!APR_BRIGADE_EMPTY(bb)) {
133 io->bbin = apr_brigade_create(io->bbout->p,
134 io->bbout->bucket_alloc);
136 return h2_util_move(io->bbin, bb, 0, NULL, "h2_io_in_write");
141 apr_status_t h2_io_in_close(h2_io *io)
144 return APR_ECONNABORTED;
148 APR_BRIGADE_INSERT_TAIL(io->bbin,
149 apr_bucket_eos_create(io->bbin->bucket_alloc));
155 apr_status_t h2_io_out_readx(h2_io *io,
156 h2_io_data_cb *cb, void *ctx,
157 apr_size_t *plen, int *peos)
162 return APR_ECONNABORTED;
172 /* just checking length available */
173 status = h2_util_bb_avail(io->bbout, plen, peos);
176 status = h2_util_bb_readx(io->bbout, cb, ctx, plen, peos);
177 if (status == APR_SUCCESS) {
185 apr_status_t h2_io_out_read_to(h2_io *io, apr_bucket_brigade *bb,
186 apr_size_t *plen, int *peos)
189 return APR_ECONNABORTED;
199 io->eos_out = *peos = h2_util_has_eos(io->bbout, *plen);
200 return h2_util_move(bb, io->bbout, *plen, NULL, "h2_io_read_to");
203 apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb,
204 apr_size_t maxlen, int *pfile_handles_allowed)
210 return APR_ECONNABORTED;
215 /* We have already delivered an EOS bucket to a reader, no
216 * sense in storing anything more here.
218 status = apr_brigade_length(bb, 1, &len);
219 if (status == APR_SUCCESS) {
221 /* someone tries to write real data after EOS, that
222 * does not look right. */
225 /* cleanup, as if we had moved the data */
226 apr_brigade_cleanup(bb);
231 /* Let's move the buckets from the request processing in here, so
232 * that the main thread can read them when it has time/capacity.
234 * Move at most "maxlen" memory bytes. If buckets remain, it is
235 * the caller's responsibility to take care of this.
237 * We allow passing of file buckets as long as we do not have too
238 * many open files already buffered. Otherwise we will run out of
241 start_allowed = *pfile_handles_allowed;
243 status = h2_util_move(io->bbout, bb, maxlen, pfile_handles_allowed,
245 /* track # file buckets moved into our pool */
246 if (start_allowed != *pfile_handles_allowed) {
247 io->files_handles_owned += (start_allowed - *pfile_handles_allowed);
253 apr_status_t h2_io_out_close(h2_io *io)
256 return APR_ECONNABORTED;
258 if (!io->eos_out && !h2_util_has_eos(io->bbout, 0)) {
259 APR_BRIGADE_INSERT_TAIL(io->bbout,
260 apr_bucket_eos_create(io->bbout->bucket_alloc));