/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/* The maximum we'd like to write in one chunk is * the max size of a TLS record. When pushing * many frames down the h2 connection, this might * align differently because of headers and other * frames or simply as not sufficient data is * in a response body. * However keeping frames at or below this limit * should make optimizations at the layer that writes * to TLS easier.
*/ #define WRITE_SIZE_MAX (TLS_DATA_MAX)
#define BUF_REMAIN ((apr_size_t)(bmax-off))
staticvoid h2_c1_io_bb_log(conn_rec *c, int stream_id, int level, constchar *tag, apr_bucket_brigade *bb)
{ char buffer[16 * 1024]; constchar *line = "(null)"; int bmax = sizeof(buffer)/sizeof(buffer[0]); int off = 0;
apr_bucket *b;
(void)stream_id; if (bb) {
memset(buffer, 0, bmax--); for (b = APR_BRIGADE_FIRST(bb);
bmax && (b != APR_BRIGADE_SENTINEL(bb));
b = APR_BUCKET_NEXT(b)) {
len = b->length; /* file buckets will read 8000 byte chunks and split * themselves. However, we do know *exactly* how many * bytes we need where. So we read the file directly to * where we need it.
*/
status = apr_file_seek(fd, APR_SET, &offset); if (status != APR_SUCCESS) { return status;
}
status = apr_file_read(fd, io->scratch + io->slen, &len); if (status != APR_SUCCESS && status != APR_EOF) { return status;
}
io->slen += len;
} elseif (APR_BUCKET_IS_MMAP(b)) {
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, io->session->c1, "h2_c1_io(%ld): seeing mmap bucket of size %ld, scratch remain=%ld",
io->session->c1->id, (long)b->length, (long)(io->ssize - io->slen));
status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ); if (status == APR_SUCCESS) {
memcpy(io->scratch+io->slen, data, len);
io->slen += len;
}
} else {
status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ); if (status == APR_SUCCESS) {
memcpy(io->scratch+io->slen, data, len);
io->slen += len;
}
} return status;
}
if (io->is_passing) { /* recursive call, may be triggered by an H2EOS bucket
* being destroyed and triggering sending more data? */
AP_DEBUG_ASSERT(0);
ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10456) "h2_c1_io(%ld): recursive call of h2_c1_io_pass. " "Denied to prevent output corruption. This " "points to a bug in the HTTP/2 implementation.",
c->id); return APR_EGENERAL;
}
io->is_passing = 1;
append_scratch(io); if (flush) { if (!APR_BUCKET_IS_FLUSH(APR_BRIGADE_LAST(io->output))) {
apr_bucket *b = apr_bucket_flush_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(io->output, b);
}
} if (APR_BRIGADE_EMPTY(io->output)) {
rv = APR_SUCCESS; goto cleanup;
}
/* H2_IN filter handles all incoming data against the session.
* We just pull at the filter chain to make it happen */
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c1,
H2_SSSN_MSG(session, "session_read start"));
rv = read_and_feed(session);
if (APR_SUCCESS == rv) {
h2_session_dispatch_event(session, H2_SESSION_EV_INPUT_PENDING, 0, NULL);
} elseif (APR_STATUS_IS_EAGAIN(rv)) { /* Signal that we have exhausted the input momentarily.
* This might switch to polling the socket */
h2_session_dispatch_event(session, H2_SESSION_EV_INPUT_EXHAUSTED, 0, NULL);
} elseif (APR_SUCCESS != rv) { if (APR_STATUS_IS_ETIMEDOUT(rv)
|| APR_STATUS_IS_ECONNABORTED(rv)
|| APR_STATUS_IS_ECONNRESET(rv)
|| APR_STATUS_IS_EOF(rv)
|| APR_STATUS_IS_EBADF(rv)) { /* common status for a client that has left */
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, rv, session->c1,
H2_SSSN_MSG(session, "input gone"));
} else { /* uncommon status, log on INFO so that we see this */
ap_log_cerror( APLOG_MARK, APLOG_DEBUG, rv, session->c1,
H2_SSSN_LOG(APLOGNO(02950), session, "error reading, terminating"));
}
h2_session_dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, NULL);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.