/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
if (conn_ctx->beam_in) {
h2_beam_abort(conn_ctx->beam_in, from);
} if (conn_ctx->beam_out) {
h2_beam_abort(conn_ctx->beam_out, from);
}
c2->aborted = 1;
}
typedefstruct {
apr_bucket_brigade *bb; /* c2: data in holding area */ unsigned did_upgrade_eos:1; /* for Upgrade, we added an extra EOS */
} h2_c2_fctx_in_t;
if (!fctx) {
fctx = apr_pcalloc(f->c->pool, sizeof(*fctx));
f->ctx = fctx;
fctx->bb = apr_brigade_create(f->c->pool, f->c->bucket_alloc); if (!conn_ctx->beam_in) {
b = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(fctx->bb, b);
}
}
/* If this is a HTTP Upgrade, it means the request we process *hasnotContent,althoughthestreamisnotnecessarilyclosed. *Onfirstread,weinsertanEOStosignalprocessingthatit
* has the complete body. */ if (conn_ctx->is_upgrade && !fctx->did_upgrade_eos) {
b = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(fctx->bb, b);
fctx->did_upgrade_eos = 1;
}
while (APR_BRIGADE_EMPTY(fctx->bb)) { /* Get more input data for our request. */ if (APLOGctrace2(f->c)) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, f->c, "h2_c2_in(%s-%d): get more data from mplx, block=%d, " "readbytes=%ld",
conn_ctx->id, conn_ctx->stream_id, block, (long)readbytes);
} if (conn_ctx->beam_in) { if (conn_ctx->pipe_in[H2_PIPE_OUT]) {
receive:
status = h2_beam_receive(conn_ctx->beam_in, f->c, fctx->bb, APR_NONBLOCK_READ,
conn_ctx->mplx->stream_max_mem); if (APR_STATUS_IS_EAGAIN(status) && APR_BLOCK_READ == block) {
status = h2_util_wait_on_pipe(conn_ctx->pipe_in[H2_PIPE_OUT]); if (APR_SUCCESS == status) { goto receive;
}
}
} else {
status = h2_beam_receive(conn_ctx->beam_in, f->c, fctx->bb, block,
conn_ctx->mplx->stream_max_mem);
}
} else {
status = APR_EOF;
}
if (APLOGctrace3(f->c)) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, f->c, "h2_c2_in(%s-%d): read returned",
conn_ctx->id, conn_ctx->stream_id);
} if (APR_STATUS_IS_EAGAIN(status)
&& (mode == AP_MODE_GETLINE || block == APR_BLOCK_READ)) { /* chunked input handling does not seem to like it if we *returnwithAPR_EAGAINfromaGETLINEread...
* upload 100k test on test-ser.example.org hangs */
status = APR_SUCCESS;
} elseif (APR_STATUS_IS_EOF(status)) { break;
} elseif (status != APR_SUCCESS) {
conn_ctx->last_err = status; return status;
}
/* Nothing there, no more data to get. Return. */ if (status == APR_EOF && APR_BRIGADE_EMPTY(fctx->bb)) { return status;
}
if (APLOGctrace3(f->c)) {
h2_util_bb_log(f->c, conn_ctx->stream_id, APLOG_TRACE3, "c2 input.bb", fctx->bb);
}
if (APR_BRIGADE_EMPTY(fctx->bb)) { if (APLOGctrace3(f->c)) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, f->c, "h2_c2_in(%s-%d): no data",
conn_ctx->id, conn_ctx->stream_id);
} return (block == APR_NONBLOCK_READ)? APR_EAGAIN : APR_EOF;
}
if (mode == AP_MODE_EXHAUSTIVE) { /* return all we have */
APR_BRIGADE_CONCAT(bb, fctx->bb);
} elseif (mode == AP_MODE_READBYTES) {
status = h2_brigade_concat_length(bb, fctx->bb, rmax);
} elseif (mode == AP_MODE_SPECULATIVE) {
status = h2_brigade_copy_length(bb, fctx->bb, rmax);
} elseif (mode == AP_MODE_GETLINE) { /* we are reading a single LF line, e.g. the HTTP headers. *thishasthenastysideeffecttosplitthebucket,even
* though it ends with CRLF and creates a 0 length bucket */
status = apr_brigade_split_line(bb, fctx->bb, block,
HUGE_STRING_LEN); if (APLOGctrace3(f->c)) { char buffer[1024];
apr_size_t len = sizeof(buffer)-1;
apr_brigade_flatten(bb, buffer, &len);
buffer[len] = 0;
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, status, f->c, "h2_c2_in(%s-%d): getline: %s",
conn_ctx->id, conn_ctx->stream_id, buffer);
}
} else { /* Hmm, well. There is mode AP_MODE_EATCRLF, but we chose not
* to support it. Seems to work. */
ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOTIMPL, f->c,
APLOGNO(03472) "h2_c2_in(%s-%d), unsupported READ mode %d",
conn_ctx->id, conn_ctx->stream_id, mode);
status = APR_ENOTIMPL;
}
if (!c2->master || !(conn_ctx = h2_conn_ctx_get(c2)) || !conn_ctx->stream_id) { return DECLINED;
} /* Now that the request_rec is fully initialized, set relevant params */
conn_ctx->server = r->server;
timeout = h2_config_geti64(r, r->server, H2_CONF_STREAM_TIMEOUT); if (timeout <= 0) {
timeout = r->server->timeout;
}
h2_conn_ctx_set_timeout(conn_ctx, timeout); /* We only handle this one request on the connection and tell everyone *thatthereisnoneedtokeepit"clean"ifsomethingfails.Also, *thispreventsmod_reqtimeoutfromdoingfunnybusinesswithmonitoring *keepalivetimeouts.
*/
r->connection->keepalive = AP_CONN_CLOSE;
if (conn_ctx->beam_in && !apr_table_get(r->headers_in, "Content-Length")) {
r->body_indeterminate = 1;
}
if (h2_config_sgeti(conn_ctx->server, H2_CONF_COPY_FILES)) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "h2_mplx(%s-%d): copy_files in output",
conn_ctx->id, conn_ctx->stream_id);
h2_beam_set_copy_files(conn_ctx->beam_out, 1);
}
/* Add the raw bytes of the request (e.g. header frame lengths to
* the logio for this request. */ if (conn_ctx->request->raw_bytes && h2_c_logio_add_bytes_in) {
h2_c_logio_add_bytes_in(c2, conn_ctx->request->raw_bytes);
} return OK;
}
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c2, "h2_c2(%s-%d), adding filters",
conn_ctx->id, conn_ctx->stream_id);
ap_add_input_filter_handle(c2_net_in_filter_handle, NULL, NULL, c2);
ap_add_output_filter_handle(c2_net_out_filter_handle, NULL, NULL, c2); if (c2->keepalives == 0) { /* Simulate that we had already a request on this connection. Some *hookstriggerspecialbehaviourwhenkeepalivesis0. *(Notnecessarilyinpre_connection,butlater.Setithere,soit
* is in place.) */
c2->keepalives = 1; /* We signal that this connection will be closed after the request. *Whichistrueinthatsensethatwethrowawayalltrafficdata *onthisc2connectionaftereachrequests.Althoughwemight *reuseinternalstructureslikememorypools. *Thewantedeffectofthisisthathttpddoesnottrytocleanup *anydanglingdataonthisconnectionwhenarequestisdone.Which *isunnecessaryonah2stream.
*/
c2->keepalive = AP_CONN_CLOSE;
} return OK;
}
void h2_c2_register_hooks(void)
{ /* When the connection processing actually starts, we might *takeover,iftheconnectionisforah2stream.
*/
ap_hook_pre_connection(c2_hook_pre_connection,
NULL, NULL, APR_HOOK_MIDDLE);
/* We need to manipulate the standard HTTP/1.1 protocol filters and
* install our own. This needs to be done very early. */
ap_hook_pre_read_request(c2_pre_read_request, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_post_read_request(c2_post_read_request, NULL, NULL,
APR_HOOK_REALLY_FIRST);
ap_hook_fixups(c2_hook_fixups, NULL, NULL, APR_HOOK_LAST); #if H2_USE_POLLFD_FROM_CONN
ap_hook_get_pollfd_from_conn(http2_get_pollfd_from_conn, NULL, NULL,
APR_HOOK_MIDDLE); #endif
APR_REGISTER_OPTIONAL_FN(http2_get_pollfd_from_conn);
static apr_status_t c2_run_pre_connection(conn_rec *c2, apr_socket_t *csd)
{ if (c2->keepalives == 0) { /* Simulate that we had already a request on this connection. Some *hookstriggerspecialbehaviourwhenkeepalivesis0. *(Notnecessarilyinpre_connection,butlater.Setithere,soit
* is in place.) */
c2->keepalives = 1; /* We signal that this connection will be closed after the request. *Whichistrueinthatsensethatwethrowawayalltrafficdata *onthisc2connectionaftereachrequests.Althoughwemight *reuseinternalstructureslikememorypools. *Thewantedeffectofthisisthathttpddoesnottrytocleanup *anydanglingdataonthisconnectionwhenarequestisdone.Which *isunnecessaryonah2stream.
*/
c2->keepalive = AP_CONN_CLOSE; return ap_run_pre_connection(c2, csd);
}
ap_assert(c2->output_filters); return APR_SUCCESS;
}
/* Add the raw bytes of the request (e.g. header frame lengths to
* the logio for this request. */ if (req->raw_bytes && h2_c_logio_add_bytes_in) {
h2_c_logio_add_bytes_in(c, req->raw_bytes);
}
ap_process_request(r); /* After the call to ap_process_request, the
* request pool may have been deleted. */
r = NULL; if (conn_ctx->beam_out) {
h2_beam_close(conn_ctx->beam_out, c);
}
ap_assert(c1);
ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c1, "h2_c2: create for c1(%ld)", c1->id);
/* We create a pool with its own allocator to be used for *processingarequest.Thisistheonlywaytohavetheprocessing *independentofitsparentpoolinthesensethatitcanworkin *anotherthread.
*/
apr_pool_create(&pool, parent);
apr_pool_tag(pool, "h2_c2_conn");
/* setup the correct filters to process the request for h2 */
ap_add_input_filter("H2_C2_REQUEST_IN", NULL, r, r->connection);
/* replace the core http filter that formats response headers
* in HTTP/1 with our own that collects status and headers */
ap_remove_output_filter_byhandle(r->output_filters, "HTTP_HEADER");
void h2_c2_register_hooks(void)
{ /* When the connection processing actually starts, we might *takeover,iftheconnectionisforah2stream.
*/
ap_hook_process_connection(h2_c2_hook_process,
NULL, NULL, APR_HOOK_FIRST); /* We need to manipulate the standard HTTP/1.1 protocol filters and
* install our own. This needs to be done very early. */
ap_hook_post_read_request(h2_c2_hook_post_read_request, NULL, NULL, APR_HOOK_REALLY_FIRST);
ap_hook_fixups(c2_hook_fixups, NULL, NULL, APR_HOOK_LAST); #if H2_USE_POLLFD_FROM_CONN
ap_hook_get_pollfd_from_conn(http2_get_pollfd_from_conn, NULL, NULL,
APR_HOOK_MIDDLE); #endif
APR_REGISTER_OPTIONAL_FN(http2_get_pollfd_from_conn);
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 und die Messung sind noch experimentell.