You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2015/11/20 16:13:11 UTC
svn commit: r1715371 [1/6] - in /httpd/httpd/branches/2.4.x: ./
docs/manual/mod/ modules/http2/
Author: icing
Date: Fri Nov 20 15:13:11 2015
New Revision: 1715371
URL: http://svn.apache.org/viewvc?rev=1715371&view=rev
Log:
update of mod_http2 with current trunk version
Added:
httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.c
httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.h
httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c
httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.h
httpd/httpd/branches/2.4.x/modules/http2/h2_push.c
httpd/httpd/branches/2.4.x/modules/http2/h2_push.h
Removed:
httpd/httpd/branches/2.4.x/modules/http2/h2_to_h1.c
httpd/httpd/branches/2.4.x/modules/http2/h2_to_h1.h
Modified:
httpd/httpd/branches/2.4.x/CHANGES
httpd/httpd/branches/2.4.x/docs/manual/mod/mod_http2.xml
httpd/httpd/branches/2.4.x/modules/http2/config.m4
httpd/httpd/branches/2.4.x/modules/http2/h2_config.c
httpd/httpd/branches/2.4.x/modules/http2/h2_config.h
httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c
httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h
httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c
httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.h
httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.c
httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.h
httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c
httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.h
httpd/httpd/branches/2.4.x/modules/http2/h2_h2.c
httpd/httpd/branches/2.4.x/modules/http2/h2_h2.h
httpd/httpd/branches/2.4.x/modules/http2/h2_io.c
httpd/httpd/branches/2.4.x/modules/http2/h2_io.h
httpd/httpd/branches/2.4.x/modules/http2/h2_io_set.c
httpd/httpd/branches/2.4.x/modules/http2/h2_io_set.h
httpd/httpd/branches/2.4.x/modules/http2/h2_mplx.c
httpd/httpd/branches/2.4.x/modules/http2/h2_mplx.h
httpd/httpd/branches/2.4.x/modules/http2/h2_request.c
httpd/httpd/branches/2.4.x/modules/http2/h2_request.h
httpd/httpd/branches/2.4.x/modules/http2/h2_response.c
httpd/httpd/branches/2.4.x/modules/http2/h2_response.h
httpd/httpd/branches/2.4.x/modules/http2/h2_session.c
httpd/httpd/branches/2.4.x/modules/http2/h2_session.h
httpd/httpd/branches/2.4.x/modules/http2/h2_stream.c
httpd/httpd/branches/2.4.x/modules/http2/h2_stream.h
httpd/httpd/branches/2.4.x/modules/http2/h2_stream_set.c
httpd/httpd/branches/2.4.x/modules/http2/h2_stream_set.h
httpd/httpd/branches/2.4.x/modules/http2/h2_switch.c
httpd/httpd/branches/2.4.x/modules/http2/h2_task.c
httpd/httpd/branches/2.4.x/modules/http2/h2_task.h
httpd/httpd/branches/2.4.x/modules/http2/h2_task_input.c
httpd/httpd/branches/2.4.x/modules/http2/h2_task_input.h
httpd/httpd/branches/2.4.x/modules/http2/h2_task_output.c
httpd/httpd/branches/2.4.x/modules/http2/h2_task_output.h
httpd/httpd/branches/2.4.x/modules/http2/h2_task_queue.c
httpd/httpd/branches/2.4.x/modules/http2/h2_task_queue.h
httpd/httpd/branches/2.4.x/modules/http2/h2_util.c
httpd/httpd/branches/2.4.x/modules/http2/h2_util.h
httpd/httpd/branches/2.4.x/modules/http2/h2_version.h
httpd/httpd/branches/2.4.x/modules/http2/h2_worker.c
httpd/httpd/branches/2.4.x/modules/http2/h2_worker.h
httpd/httpd/branches/2.4.x/modules/http2/h2_workers.c
httpd/httpd/branches/2.4.x/modules/http2/h2_workers.h
httpd/httpd/branches/2.4.x/modules/http2/mod_http2.dsp
Modified: httpd/httpd/branches/2.4.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/CHANGES?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.4.x/CHANGES [utf-8] Fri Nov 20 15:13:11 2015
@@ -2,6 +2,47 @@
Changes with Apache 2.4.18
+ *) mod_http2: incoming trailers (headers after request body) are properly
+ forwarded to the processing engine. [Stefan Eissing]
+
+ *) mod_http2: new directive 'H2Push' to en-/disable HTTP/2 server
+ pushes a server/virtual host. Pushes are initiated by the presence
+ of 'Link:' headers with relation 'preload' on a response. [Stefan Eissing]
+
+ *) mod_http2: write performance of http2 improved for larger resources,
+ especially static files. [Stefan Eissing]
+
+ *) core: if the first HTTP/1.1 request on a connection goes to a server that
+ prefers different protocols, these protocols are announced in a Upgrade:
+ header on the response, mentioning the preferred protocols.
+ [Stefan Eissing]
+
+ *) mod_http2: new directives 'H2TLSWarmUpSize' and 'H2TLSCoolDownSecs'
+ to control TLS record sizes during connection lifetime.
+ [Stefan Eissing]
+
+ *) mod_http2: new directive 'H2ModernTLSOnly' to enforce security
+ requirements of RFC 7540 on TLS connections. [Stefan Eissing]
+
+ *) core: add ap_get_protocol_upgrades() to retrieve the list of protocols
+ that a client could possibly upgrade to. Use in first request on a
+ connection to announce protocol choices. [Stefan Eissing]
+
+ *) mod_http2: reworked deallocation on connection shutdown and worker
+ abort. Separate parent pool for all workers. worker threads are joined
+ on planned worker shutdown. [Yann Ylavic, Stefan Eissing]
+
+ *) mod_ssl: when receiving requests for other virtual hosts than the handshake
+ server, the SSL parameters are checked for equality. With equal
+ configuration, requests are passed for processing. Any change will trigger
+ the old behaviour of "421 Misdirected Request".
+ SSL now remembers the cipher suite that was used for the last handshake.
+ This is compared against for any vhost/directory cipher specification.
+ Detailed examination of renegotiation is only done when these do not
+ match.
+ Renegotiation is 403ed when a master connection is present. Exact reason
+ is given additionally in a request note. [Stefan Eissing]
+
*) core: Fix scoreboard crash (SIGBUS) on hardware requiring strict 64bit
alignment (SPARC64, PPC64). [Yann Ylavic]
Modified: httpd/httpd/branches/2.4.x/docs/manual/mod/mod_http2.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/docs/manual/mod/mod_http2.xml?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/mod/mod_http2.xml (original)
+++ httpd/httpd/branches/2.4.x/docs/manual/mod/mod_http2.xml Fri Nov 20 15:13:11 2015
@@ -42,13 +42,22 @@
release relative to other standard modules. Users are encouraged to
consult the "CHANGES" file for potential updates.</p>
</note>
+
+ <p>You must enable HTTP/2 via <directive
+ module="core">Protocols</directive> in order to use the
+ functionality described in this document:</p>
+
+ <highlight language="config">
+ Protocols h2 http/1.1
+ </highlight>
+
</summary>
<directivesynopsis>
<name>H2Direct</name>
<description>H2 Direct Protocol Switch</description>
<syntax>H2Direct on|off</syntax>
- <default>H2Direct on (for non TLS)</default>
+ <default>H2Direct on for h2c, off for h2 protocol</default>
<contextlist>
<context>server config</context>
<context>virtual host</context>
@@ -60,12 +69,31 @@
should be used inside a
<directive module="core" type="section">VirtualHost</directive>
section to enable direct HTTP/2 communication for that virtual host.
+ </p>
+ <p>
Direct communication means that if the first bytes received by the
server on a connection match the HTTP/2 preamble, the HTTP/2
protocol is switched to immediately without further negotiation.
- This mode falls outside the RFC 7540 but has become widely implemented
- as it is very convenient for development and testing.
- By default the direct HTTP/2 mode is enabled.
+ This mode is defined in RFC 7540 for the cleartext (h2c) case. Its
+ use on TLS connections not mandated by the standard.
+ </p>
+ <p>
+ When a server/vhost does not have h2 or h2c enabled via
+ <directive module="core" type="section">Protocols</directive>,
+ the connection is never inspected for a HTTP/2 preamble. H2Direct
+ does not matter then. This is important for connections that
+ use protocols where an initial read might hang indefinitely, such
+ as NNTP.
+ </p>
+ <p>
+ For clients that have out-of-band knowledge about a server
+ supporting h2c, direct HTTP/2 saves the client from having to
+ perform an HTTP/1.1 upgrade, resulting in better performance
+ and avoiding the Upgrade restrictions on request bodies.
+ </p>
+ <p>
+ This makes direct h2c attractive for server to server communication
+ as well, when the connection can be trusted or is secured by other means.
</p>
<example><title>Example</title>
<highlight language="config">
@@ -74,6 +102,122 @@
</example>
</usage>
</directivesynopsis>
+
+ <directivesynopsis>
+ <name>H2Push</name>
+ <description>H2 Server Push Switch</description>
+ <syntax>H2Push on|off</syntax>
+ <default>H2Push on</default>
+ <contextlist>
+ <context>server config</context>
+ <context>virtual host</context>
+ </contextlist>
+
+ <usage>
+ <p>
+ This directive toggles the usage of the HTTP/2 server push
+ protocol feature. This should be used inside a
+ <directive module="core" type="section">VirtualHost</directive>
+ section to enable direct HTTP/2 communication for that virtual host.
+ </p>
+ <p>
+ The HTTP/2 protocol allows the server to push other resources to
+ a client when it asked for a particular one. This is helpful
+ if those resources are connected in some way and the client can
+ be expected to ask for it anyway. The pushing then saves the
+ time it takes the client to ask for the resources itself. On the
+ other hand, pushing resources the client never needs or already
+ has is a waste of bandwidth.
+ </p>
+ <p>
+ Server pushes are detected by inspecting the <code>Link</code> headers of
+ responses (see https://tools.ietf.org/html/rfc5988 for the
+ specification). When a link thus specified has the <code>rel=preload</code>
+ attribute, it is treated as a resource to be pushed.
+ </p>
+ <p>
+ Link headers in responses are either set by the application or
+ can be configured via <module>mod_headers</module> as:
+ </p>
+ <example><title>mod_headers example</title>
+ <highlight language="config">
+<Location /index.html>
+ Header add Link "</css/site.css>;rel=preload"
+ Header add Link "</images/logo.jpg>;rel=preload"
+</Location>
+ </highlight>
+ </example>
+ <p>
+ As the example shows, there can be several link headers added
+ to a response, resulting in several pushes being triggered. There
+ are no checks in the module to avoid pushing the same resource
+ twice or more to one client. Use with care.
+ </p>
+ <p>
+ HTTP/2 server pushes are enabled by default. This directive
+ allows it to be switch off on all resources of this server/virtual
+ host.
+ </p>
+ <example><title>Example</title>
+ <highlight language="config">
+ H2Push off
+ </highlight>
+ </example>
+ <p>
+ Last but not least, pushes happen only when the client signals
+ its willingness to accept those. Most browsers do, some, like Safari 9,
+ do not.
+ </p>
+ </usage>
+ </directivesynopsis>
+
+ <directivesynopsis>
+ <name>H2Upgrade</name>
+ <description>H2 Upgrade Protocol Switch</description>
+ <syntax>H2Upgrade on|off</syntax>
+ <default>H2Upgrade on for h2c, off for h2 protocol</default>
+ <contextlist>
+ <context>server config</context>
+ <context>virtual host</context>
+ </contextlist>
+
+ <usage>
+ <p>
+ This directive toggles the usage of the HTTP/1.1 Upgrade method
+ for switching to HTTP/2. This
+ should be used inside a
+ <directive module="core" type="section">VirtualHost</directive>
+ section to enable Upgrades to HTTP/2 for that virtual host.
+ </p>
+ <p>
+ This method of switching protocols is defined in HTTP/1.1 and
+ uses the "Upgrade" header (thus the name) to announce willingness
+ to use another protocol. This may happen on any request of a
+ HTTP/1.1 connection.
+ </p>
+ <p>
+ This method of protocol switching is enabled by default on cleartext
+ (potential h2c) connections and disabled on TLS (potential h2),
+ as mandated by RFC 7540.
+ </p>
+ <p>
+ Please be aware that Upgrades are only accepted for requests
+ that carry no body. POSTs and PUTs with content will never
+ trigger an upgrade to HTTP/2.
+ See <directive type="section">H2Direct</directive> for an
+ alternative to Upgrade.
+ </p>
+ <p>
+ This mode only has an effect when h2 or h2c is enabled via
+ the <directive module="core" type="section">Protocols</directive>.
+ </p>
+ <example><title>Example</title>
+ <highlight language="config">
+ H2Upgrade on
+ </highlight>
+ </example>
+ </usage>
+ </directivesynopsis>
<directivesynopsis>
<name>H2MaxSessionStreams</name>
@@ -230,7 +374,7 @@
<p>
This directive sets maximum number of <em>extra</em> file handles
a HTTP/2 session is allowed to use. A file handle is counted as
- <em>extra</em> when it is transfered from a h2 worker thread to
+ <em>extra</em> when it is transferred from a h2 worker thread to
the main HTTP/2 connection handling. This commonly happens when
serving static files.
</p><p>
@@ -282,4 +426,147 @@
</usage>
</directivesynopsis>
+ <directivesynopsis>
+ <name>H2ModernTLSOnly</name>
+ <description>Require HTTP/2 connections to be "modern TLS" only</description>
+ <syntax>H2ModernTLSOnly on|off</syntax>
+ <default>H2ModernTLSOnly on</default>
+ <contextlist>
+ <context>server config</context>
+ <context>virtual host</context>
+ </contextlist>
+
+ <usage>
+ <p>
+ This directive toggles the security checks on HTTP/2 connections
+ in TLS mode (https:). This can be used server wide or for specific
+ <directive module="core" type="section">VirtualHost</directive>s.
+ </p>
+ <p>
+ The security checks require that the TSL protocol is at least
+ TLSv1.2 and that none of the ciphers listed in RFC 7540, Appendix A
+ is used. These checks will be extended once new security requirements
+ come into place.
+ </p>
+ <p>
+ The name stems from the
+ <a href="https://wiki.mozilla.org/Security/Server_Side_TLS">Security/Server Side TLS</a>
+ definitions at mozilla where "modern compatibility" is defined. Mozilla Firefox and
+ other browsers require modern compatibility for HTTP/2 connections. As everything
+ in OpSec, this is a moving target and can be expected to evolve in the future.
+ </p>
+ <p>
+ One purpose of having these checks in mod_http2 is to enforce this
+ security level for all connections, not only those from browsers. The other
+ purpose is to prevent the negotiation of HTTP/2 as a protocol should
+ the requirements not be met.
+ </p>
+ <p>
+ Ultimately, the security of the TLS connection is determined by the
+ server configuration directives for mod_ssl.
+ </p>
+ <example><title>Example</title>
+ <highlight language="config">
+ H2ModernTLSOnly off
+ </highlight>
+ </example>
+ </usage>
+ </directivesynopsis>
+
+ <directivesynopsis>
+ <name>H2TLSWarmUpSize</name>
+ <description></description>
+ <syntax>H2TLSWarmUpSize amount</syntax>
+ <default>H2TLSWarmUpSize 1048576</default>
+ <contextlist>
+ <context>server config</context>
+ <context>virtual host</context>
+ </contextlist>
+
+ <usage>
+ <p>
+ This directive sets the number of bytes to be sent in small
+ TLS records (~1300 bytes) until doing maximum sized writes (16k)
+ on https: HTTP/2 connections.
+ This can be used server wide or for specific
+ <directive module="core" type="section">VirtualHost</directive>s.
+ </p>
+ <p>
+ Measurements by <a href="https://www.igvita.com">google performance
+ labs</a> show that best performance on TLS connections is reached,
+ if initial record sizes stay below the MTU level, to allow a
+ complete record to fit into an IP packet.
+ </p>
+ <p>
+ While TCP adjust its flow-control and window sizes, longer TLS
+ records can get stuck in queues or get lost and need retransmission.
+ This is of course true for all packets. TLS however needs the
+ whole record in order to decrypt it. Any missing bytes at the end
+ will stall usage of the received ones.
+ </p>
+ <p>
+ After a sufficient number of bytes have been send successfully,
+ the TCP state of the connection is stable and maximum TLS record
+ sizes (16 KB) can be used for optimal performance.
+ </p>
+ <p>
+ In deployments where servers are reached locally or over reliable
+ connections only, the value might be decreased with 0 disabling
+ any warmup phase altogether.
+ </p>
+ <p>
+ The following example sets the size to zero, effectively disabling
+ any warmup phase.
+ </p>
+ <example><title>Example</title>
+ <highlight language="config">
+ H2TLSWarmUpSize 0
+ </highlight>
+ </example>
+ </usage>
+ </directivesynopsis>
+
+ <directivesynopsis>
+ <name>H2TLSCoolDownSecs</name>
+ <description></description>
+ <syntax>H2TLSCoolDownSecs seconds</syntax>
+ <default>H2TLSCoolDownSecs 1</default>
+ <contextlist>
+ <context>server config</context>
+ <context>virtual host</context>
+ </contextlist>
+
+ <usage>
+ <p>
+ This directive sets the number of seconds of idle time on a TLS
+ connection before the TLS write size falls back to small (~1300 bytes)
+ length.
+ This can be used server wide or for specific
+ <directive module="core" type="section">VirtualHost</directive>s.
+ </p>
+ <p>
+ See <directive type="section">H2TLSWarmUpSize</directive> for a
+ description of TLS warmup. H2TLSCoolDownSecs reflects the fact
+ that connections may deteriorate over time (and TCP flow adjusts)
+ for idle connections as well. It is beneficial to overall performance
+ to fall back to the pre-warmup phase after a number of seconds that
+ no data has been sent.
+ </p>
+ <p>
+ In deployments where connections can be considered reliable, this
+ timer can be disabled by setting it to 0.
+ </p>
+ <p>
+ The following example sets the seconds to zero, effectively disabling
+ any cool down. Warmed up TLS connections stay on maximum record
+ size.
+ </p>
+ <example><title>Example</title>
+ <highlight language="config">
+ H2TLSCoolDownSecs 0
+ </highlight>
+ </example>
+ </usage>
+ </directivesynopsis>
+
</modulesynopsis>
Modified: httpd/httpd/branches/2.4.x/modules/http2/config.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/config.m4?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/config.m4 (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/config.m4 Fri Nov 20 15:13:11 2015
@@ -20,6 +20,8 @@ dnl # list of module object files
http2_objs="dnl
mod_http2.lo dnl
h2_alt_svc.lo dnl
+h2_bucket_eoc.lo dnl
+h2_bucket_eos.lo dnl
h2_config.lo dnl
h2_conn.lo dnl
h2_conn_io.lo dnl
@@ -29,6 +31,7 @@ h2_h2.lo dnl
h2_io.lo dnl
h2_io_set.lo dnl
h2_mplx.lo dnl
+h2_push.lo dnl
h2_request.lo dnl
h2_response.lo dnl
h2_session.lo dnl
@@ -39,7 +42,6 @@ h2_task.lo dnl
h2_task_input.lo dnl
h2_task_output.lo dnl
h2_task_queue.lo dnl
-h2_to_h1.lo dnl
h2_util.lo dnl
h2_worker.lo dnl
h2_workers.lo dnl
Added: httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.c?rev=1715371&view=auto
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.c (added)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.c Fri Nov 20 15:13:11 2015
@@ -0,0 +1,108 @@
+/* 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.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+
+#include <httpd.h>
+#include <http_core.h>
+#include <http_connection.h>
+#include <http_log.h>
+
+#include "h2_private.h"
+#include "h2_mplx.h"
+#include "h2_session.h"
+#include "h2_bucket_eoc.h"
+
+typedef struct {
+ apr_bucket_refcount refcount;
+ h2_session *session;
+} h2_bucket_eoc;
+
+static apr_status_t bucket_cleanup(void *data)
+{
+ h2_session **psession = data;
+
+ if (*psession) {
+ /*
+ * If bucket_destroy is called after us, this prevents
+ * bucket_destroy from trying to destroy the pool again.
+ */
+ *psession = NULL;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ (void)b;
+ (void)block;
+ *str = NULL;
+ *len = 0;
+ return APR_SUCCESS;
+}
+
+apr_bucket * h2_bucket_eoc_make(apr_bucket *b, h2_session *session)
+{
+ h2_bucket_eoc *h;
+
+ h = apr_bucket_alloc(sizeof(*h), b->list);
+ h->session = session;
+
+ b = apr_bucket_shared_make(b, h, 0, 0);
+ b->type = &h2_bucket_type_eoc;
+
+ return b;
+}
+
+apr_bucket * h2_bucket_eoc_create(apr_bucket_alloc_t *list, h2_session *session)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ b = h2_bucket_eoc_make(b, session);
+ if (session) {
+ h2_bucket_eoc *h = b->data;
+ apr_pool_pre_cleanup_register(session->pool, &h->session, bucket_cleanup);
+ }
+ return b;
+}
+
+static void bucket_destroy(void *data)
+{
+ h2_bucket_eoc *h = data;
+
+ if (apr_bucket_shared_destroy(h)) {
+ h2_session *session = h->session;
+ if (session) {
+ h2_session_eoc_callback(session);
+ }
+ apr_bucket_free(h);
+ }
+}
+
+const apr_bucket_type_t h2_bucket_type_eoc = {
+ "H2EOC", 5, APR_BUCKET_METADATA,
+ bucket_destroy,
+ bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_split_notimpl,
+ apr_bucket_shared_copy
+};
+
Added: httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.h?rev=1715371&view=auto
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.h (added)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eoc.h Fri Nov 20 15:13:11 2015
@@ -0,0 +1,31 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed 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.
+ */
+
+#ifndef mod_http2_h2_bucket_eoc_h
+#define mod_http2_h2_bucket_eoc_h
+
+struct h2_session;
+
+/** End Of HTTP/2 SESSION (H2EOC) bucket */
+extern const apr_bucket_type_t h2_bucket_type_eoc;
+
+
+apr_bucket * h2_bucket_eoc_make(apr_bucket *b,
+ struct h2_session *session);
+
+apr_bucket * h2_bucket_eoc_create(apr_bucket_alloc_t *list,
+ struct h2_session *session);
+
+#endif /* mod_http2_h2_bucket_eoc_h */
Added: httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c?rev=1715371&view=auto
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c (added)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c Fri Nov 20 15:13:11 2015
@@ -0,0 +1,109 @@
+/* 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.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+
+#include <httpd.h>
+#include <http_core.h>
+#include <http_connection.h>
+#include <http_log.h>
+
+#include "h2_private.h"
+#include "h2_mplx.h"
+#include "h2_stream.h"
+#include "h2_bucket_eos.h"
+
+typedef struct {
+ apr_bucket_refcount refcount;
+ h2_stream *stream;
+} h2_bucket_eos;
+
+static apr_status_t bucket_cleanup(void *data)
+{
+ h2_stream **pstream = data;
+
+ if (*pstream) {
+ /*
+ * If bucket_destroy is called after us, this prevents
+ * bucket_destroy from trying to destroy the pool again.
+ */
+ *pstream = NULL;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ (void)b;
+ (void)block;
+ *str = NULL;
+ *len = 0;
+ return APR_SUCCESS;
+}
+
+apr_bucket *h2_bucket_eos_make(apr_bucket *b, h2_stream *stream)
+{
+ h2_bucket_eos *h;
+
+ h = apr_bucket_alloc(sizeof(*h), b->list);
+ h->stream = stream;
+
+ b = apr_bucket_shared_make(b, h, 0, 0);
+ b->type = &h2_bucket_type_eos;
+
+ return b;
+}
+
+apr_bucket *h2_bucket_eos_create(apr_bucket_alloc_t *list,
+ h2_stream *stream)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ b = h2_bucket_eos_make(b, stream);
+ if (stream) {
+ h2_bucket_eos *h = b->data;
+ apr_pool_pre_cleanup_register(stream->pool, &h->stream, bucket_cleanup);
+ }
+ return b;
+}
+
+static void bucket_destroy(void *data)
+{
+ h2_bucket_eos *h = data;
+
+ if (apr_bucket_shared_destroy(h)) {
+ h2_stream *stream = h->stream;
+ if (stream) {
+ h2_stream_cleanup(stream);
+ }
+ apr_bucket_free(h);
+ }
+}
+
+const apr_bucket_type_t h2_bucket_type_eos = {
+ "H2EOS", 5, APR_BUCKET_METADATA,
+ bucket_destroy,
+ bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_split_notimpl,
+ apr_bucket_shared_copy
+};
+
Added: httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.h?rev=1715371&view=auto
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.h (added)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.h Fri Nov 20 15:13:11 2015
@@ -0,0 +1,30 @@
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed 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.
+ */
+
+#ifndef mod_http2_h2_bucket_stream_eos_h
+#define mod_http2_h2_bucket_stream_eos_h
+
+struct h2_stream;
+
+/** End Of HTTP/2 STREAM (H2EOS) bucket */
+extern const apr_bucket_type_t h2_bucket_type_eos;
+
+
+apr_bucket *h2_bucket_eos_make(apr_bucket *b, struct h2_stream *stream);
+
+apr_bucket *h2_bucket_eos_create(apr_bucket_alloc_t *list,
+ struct h2_stream *stream);
+
+#endif /* mod_http2_h2_bucket_stream_eos_h */
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_config.c?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_config.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_config.c Fri Nov 20 15:13:11 2015
@@ -29,6 +29,7 @@
#include "h2_ctx.h"
#include "h2_conn.h"
#include "h2_config.h"
+#include "h2_h2.h"
#include "h2_private.h"
#define DEF_VAL (-1)
@@ -38,17 +39,22 @@
static h2_config defconf = {
"default",
- 100, /* max_streams */
- 64 * 1024, /* window_size */
- -1, /* min workers */
- -1, /* max workers */
- 10 * 60, /* max workers idle secs */
- 64 * 1024, /* stream max mem size */
- NULL, /* no alt-svcs */
- -1, /* alt-svc max age */
- 0, /* serialize headers */
- -1, /* h2 direct mode */
- -1, /* # session extra files */
+ 100, /* max_streams */
+ H2_INITIAL_WINDOW_SIZE, /* window_size */
+ -1, /* min workers */
+ -1, /* max workers */
+ 10 * 60, /* max workers idle secs */
+ 64 * 1024, /* stream max mem size */
+ NULL, /* no alt-svcs */
+ -1, /* alt-svc max age */
+ 0, /* serialize headers */
+ -1, /* h2 direct mode */
+ -1, /* # session extra files */
+ 1, /* modern TLS only */
+ -1, /* HTTP/1 Upgrade support */
+ 1024*1024, /* TLS warmup size */
+ 1, /* TLS cooldown secs */
+ 1, /* HTTP/2 server push enabled */
};
static int files_per_session = 0;
@@ -100,6 +106,12 @@ static void *h2_config_create(apr_pool_t
conf->serialize_headers = DEF_VAL;
conf->h2_direct = DEF_VAL;
conf->session_extra_files = DEF_VAL;
+ conf->modern_tls_only = DEF_VAL;
+ conf->h2_upgrade = DEF_VAL;
+ conf->tls_warmup_size = DEF_VAL;
+ conf->tls_cooldown_secs = DEF_VAL;
+ conf->h2_push = DEF_VAL;
+
return conf;
}
@@ -127,23 +139,33 @@ void *h2_config_merge(apr_pool_t *pool,
strcat(name, "]");
n->name = name;
- n->h2_max_streams = H2_CONFIG_GET(add, base, h2_max_streams);
- n->h2_window_size = H2_CONFIG_GET(add, base, h2_window_size);
- n->min_workers = H2_CONFIG_GET(add, base, min_workers);
- n->max_workers = H2_CONFIG_GET(add, base, max_workers);
+ n->h2_max_streams = H2_CONFIG_GET(add, base, h2_max_streams);
+ n->h2_window_size = H2_CONFIG_GET(add, base, h2_window_size);
+ n->min_workers = H2_CONFIG_GET(add, base, min_workers);
+ n->max_workers = H2_CONFIG_GET(add, base, max_workers);
n->max_worker_idle_secs = H2_CONFIG_GET(add, base, max_worker_idle_secs);
- n->stream_max_mem_size = H2_CONFIG_GET(add, base, stream_max_mem_size);
- n->alt_svcs = add->alt_svcs? add->alt_svcs : base->alt_svcs;
- n->alt_svc_max_age = H2_CONFIG_GET(add, base, alt_svc_max_age);
- n->serialize_headers = H2_CONFIG_GET(add, base, serialize_headers);
- n->h2_direct = H2_CONFIG_GET(add, base, h2_direct);
- n->session_extra_files = H2_CONFIG_GET(add, base, session_extra_files);
+ n->stream_max_mem_size = H2_CONFIG_GET(add, base, stream_max_mem_size);
+ n->alt_svcs = add->alt_svcs? add->alt_svcs : base->alt_svcs;
+ n->alt_svc_max_age = H2_CONFIG_GET(add, base, alt_svc_max_age);
+ n->serialize_headers = H2_CONFIG_GET(add, base, serialize_headers);
+ n->h2_direct = H2_CONFIG_GET(add, base, h2_direct);
+ n->session_extra_files = H2_CONFIG_GET(add, base, session_extra_files);
+ n->modern_tls_only = H2_CONFIG_GET(add, base, modern_tls_only);
+ n->h2_upgrade = H2_CONFIG_GET(add, base, h2_upgrade);
+ n->tls_warmup_size = H2_CONFIG_GET(add, base, tls_warmup_size);
+ n->tls_cooldown_secs = H2_CONFIG_GET(add, base, tls_cooldown_secs);
+ n->h2_push = H2_CONFIG_GET(add, base, h2_push);
return n;
}
int h2_config_geti(h2_config *conf, h2_config_var_t var)
{
+ return (int)h2_config_geti64(conf, var);
+}
+
+apr_int64_t h2_config_geti64(h2_config *conf, h2_config_var_t var)
+{
int n;
switch(var) {
case H2_CONF_MAX_STREAMS:
@@ -162,6 +184,10 @@ int h2_config_geti(h2_config *conf, h2_c
return H2_CONFIG_GET(conf, &defconf, alt_svc_max_age);
case H2_CONF_SER_HEADERS:
return H2_CONFIG_GET(conf, &defconf, serialize_headers);
+ case H2_CONF_MODERN_TLS_ONLY:
+ return H2_CONFIG_GET(conf, &defconf, modern_tls_only);
+ case H2_CONF_UPGRADE:
+ return H2_CONFIG_GET(conf, &defconf, h2_upgrade);
case H2_CONF_DIRECT:
return H2_CONFIG_GET(conf, &defconf, h2_direct);
case H2_CONF_SESSION_FILES:
@@ -170,6 +196,12 @@ int h2_config_geti(h2_config *conf, h2_c
n = files_per_session;
}
return n;
+ case H2_CONF_TLS_WARMUP_SIZE:
+ return H2_CONFIG_GET(conf, &defconf, tls_warmup_size);
+ case H2_CONF_TLS_COOLDOWN_SECS:
+ return H2_CONFIG_GET(conf, &defconf, tls_cooldown_secs);
+ case H2_CONF_PUSH:
+ return H2_CONFIG_GET(conf, &defconf, h2_push);
default:
return DEF_VAL;
}
@@ -290,8 +322,8 @@ static const char *h2_conf_set_session_e
{
h2_config *cfg = h2_config_sget(parms->server);
apr_int64_t max = (int)apr_atoi64(value);
- if (max <= 0) {
- return "value must be a positive number";
+ if (max < 0) {
+ return "value must be a non-negative number";
}
cfg->session_extra_files = (int)max;
(void)arg;
@@ -332,8 +364,77 @@ static const char *h2_conf_set_direct(cm
return "value must be On or Off";
}
-#define AP_END_CMD AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL)
+static const char *h2_conf_set_push(cmd_parms *parms,
+ void *arg, const char *value)
+{
+ h2_config *cfg = h2_config_sget(parms->server);
+ if (!strcasecmp(value, "On")) {
+ cfg->h2_push = 1;
+ return NULL;
+ }
+ else if (!strcasecmp(value, "Off")) {
+ cfg->h2_push = 0;
+ return NULL;
+ }
+
+ (void)arg;
+ return "value must be On or Off";
+}
+
+static const char *h2_conf_set_modern_tls_only(cmd_parms *parms,
+ void *arg, const char *value)
+{
+ h2_config *cfg = h2_config_sget(parms->server);
+ if (!strcasecmp(value, "On")) {
+ cfg->modern_tls_only = 1;
+ return NULL;
+ }
+ else if (!strcasecmp(value, "Off")) {
+ cfg->modern_tls_only = 0;
+ return NULL;
+ }
+
+ (void)arg;
+ return "value must be On or Off";
+}
+
+static const char *h2_conf_set_upgrade(cmd_parms *parms,
+ void *arg, const char *value)
+{
+ h2_config *cfg = h2_config_sget(parms->server);
+ if (!strcasecmp(value, "On")) {
+ cfg->h2_upgrade = 1;
+ return NULL;
+ }
+ else if (!strcasecmp(value, "Off")) {
+ cfg->h2_upgrade = 0;
+ return NULL;
+ }
+
+ (void)arg;
+ return "value must be On or Off";
+}
+
+static const char *h2_conf_set_tls_warmup_size(cmd_parms *parms,
+ void *arg, const char *value)
+{
+ h2_config *cfg = h2_config_sget(parms->server);
+ cfg->tls_warmup_size = apr_atoi64(value);
+ (void)arg;
+ return NULL;
+}
+static const char *h2_conf_set_tls_cooldown_secs(cmd_parms *parms,
+ void *arg, const char *value)
+{
+ h2_config *cfg = h2_config_sget(parms->server);
+ cfg->tls_cooldown_secs = (int)apr_atoi64(value);
+ (void)arg;
+ return NULL;
+}
+
+
+#define AP_END_CMD AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL)
const command_rec h2_cmds[] = {
AP_INIT_TAKE1("H2MaxSessionStreams", h2_conf_set_max_streams, NULL,
@@ -354,10 +455,20 @@ const command_rec h2_cmds[] = {
RSRC_CONF, "set the maximum age (in seconds) that client can rely on alt-svc information"),
AP_INIT_TAKE1("H2SerializeHeaders", h2_conf_set_serialize_headers, NULL,
RSRC_CONF, "on to enable header serialization for compatibility"),
+ AP_INIT_TAKE1("H2ModernTLSOnly", h2_conf_set_modern_tls_only, NULL,
+ RSRC_CONF, "off to not impose RFC 7540 restrictions on TLS"),
+ AP_INIT_TAKE1("H2Upgrade", h2_conf_set_upgrade, NULL,
+ RSRC_CONF, "on to allow HTTP/1 Upgrades to h2/h2c"),
AP_INIT_TAKE1("H2Direct", h2_conf_set_direct, NULL,
RSRC_CONF, "on to enable direct HTTP/2 mode"),
AP_INIT_TAKE1("H2SessionExtraFiles", h2_conf_set_session_extra_files, NULL,
RSRC_CONF, "number of extra file a session might keep open"),
+ AP_INIT_TAKE1("H2TLSWarmUpSize", h2_conf_set_tls_warmup_size, NULL,
+ RSRC_CONF, "number of bytes on TLS connection before doing max writes"),
+ AP_INIT_TAKE1("H2TLSCoolDownSecs", h2_conf_set_tls_cooldown_secs, NULL,
+ RSRC_CONF, "seconds of idle time on TLS before shrinking writes"),
+ AP_INIT_TAKE1("H2Push", h2_conf_set_push, NULL,
+ RSRC_CONF, "off to disable HTTP/2 server push"),
AP_END_CMD
};
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_config.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_config.h?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_config.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_config.h Fri Nov 20 15:13:11 2015
@@ -34,6 +34,11 @@ typedef enum {
H2_CONF_SER_HEADERS,
H2_CONF_DIRECT,
H2_CONF_SESSION_FILES,
+ H2_CONF_MODERN_TLS_ONLY,
+ H2_CONF_UPGRADE,
+ H2_CONF_TLS_WARMUP_SIZE,
+ H2_CONF_TLS_COOLDOWN_SECS,
+ H2_CONF_PUSH,
} h2_config_var_t;
/* Apache httpd module configuration for h2. */
@@ -51,6 +56,11 @@ typedef struct h2_config {
processing, better compatibility */
int h2_direct; /* if mod_h2 is active directly */
int session_extra_files; /* # of extra files a session may keep open */
+ int modern_tls_only; /* Accept only modern TLS in HTTP/2 connections */
+ int h2_upgrade; /* Allow HTTP/1 upgrade to h2/h2c */
+ apr_int64_t tls_warmup_size; /* Amount of TLS data to send before going full write size */
+ int tls_cooldown_secs; /* Seconds of idle time before going back to small TLS records */
+ int h2_push; /* if HTTP/2 server push is enabled */
} h2_config;
@@ -67,6 +77,7 @@ h2_config *h2_config_sget(server_rec *s)
h2_config *h2_config_rget(request_rec *r);
int h2_config_geti(h2_config *conf, h2_config_var_t var);
+apr_int64_t h2_config_geti64(h2_config *conf, h2_config_var_t var);
void h2_config_init(apr_pool_t *pool);
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c Fri Nov 20 15:13:11 2015
@@ -32,6 +32,7 @@
#include "h2_session.h"
#include "h2_stream.h"
#include "h2_stream_set.h"
+#include "h2_h2.h"
#include "h2_task.h"
#include "h2_worker.h"
#include "h2_workers.h"
@@ -39,11 +40,8 @@
static struct h2_workers *workers;
-static apr_status_t h2_session_process(h2_session *session);
-
static h2_mpm_type_t mpm_type = H2_MPM_UNKNOWN;
static module *mpm_module;
-static module *ssl_module;
static int checked;
static void check_modules(void)
@@ -64,9 +62,6 @@ static void check_modules(void)
mpm_type = H2_MPM_PREFORK;
mpm_module = m;
}
- else if (!strcmp("mod_ssl.c", m->name)) {
- ssl_module = m;
- }
}
checked = 1;
}
@@ -103,9 +98,6 @@ apr_status_t h2_conn_child_init(apr_pool
mpm_type = H2_MPM_PREFORK;
mpm_module = m;
}
- else if (!strcmp("mod_ssl.c", m->name)) {
- ssl_module = m;
- }
}
if (minw <= 0) {
@@ -139,228 +131,70 @@ static module *h2_conn_mpm_module(void)
return mpm_module;
}
-apr_status_t h2_conn_rprocess(request_rec *r)
+apr_status_t h2_conn_process(conn_rec *c, request_rec *r)
{
- h2_config *config = h2_config_rget(r);
+ apr_status_t status;
h2_session *session;
+ h2_config *config;
+ int rv;
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "h2_conn_process start");
if (!workers) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02911)
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02911)
"workers not initialized");
return APR_EGENERAL;
}
- session = h2_session_rcreate(r, config, workers);
- if (!session) {
- return APR_EGENERAL;
- }
-
- return h2_session_process(session);
-}
-
-apr_status_t h2_conn_main(conn_rec *c)
-{
- h2_config *config = h2_config_get(c);
- h2_session *session;
- apr_status_t status;
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "h2_conn_process start");
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "h2_conn_main start");
- if (!workers) {
- ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02912)
- "workers not initialized");
- return APR_EGENERAL;
- }
-
- session = h2_session_create(c, config, workers);
- if (!session) {
- return APR_EGENERAL;
+ if (r) {
+ config = h2_config_rget(r);
+ session = h2_session_rcreate(r, config, workers);
}
-
- status = h2_session_process(session);
-
- /* Make sure this connection gets closed properly. */
- c->keepalive = AP_CONN_CLOSE;
- if (c->cs) {
- c->cs->state = CONN_STATE_WRITE_COMPLETION;
+ else {
+ config = h2_config_get(c);
+ session = h2_session_create(c, config, workers);
}
-
- return status;
-}
-
-apr_status_t h2_session_process(h2_session *session)
-{
- apr_status_t status = APR_SUCCESS;
- int rv = 0;
- apr_interval_time_t wait_micros = 0;
- static const int MAX_WAIT_MICROS = 200 * 1000;
-
- /* Start talking to the client. Apart from protocol meta data,
- * we mainly will see new http/2 streams opened by the client, which
- * basically are http requests we need to dispatch.
- *
- * There will be bursts of new streams, to be served concurrently,
- * followed by long pauses of no activity.
- *
- * Since the purpose of http/2 is to allow siumultaneous streams, we
- * need to dispatch the handling of each stream into a separate worker
- * thread, keeping this thread open for sending responses back as
- * soon as they arrive.
- * At the same time, we need to continue reading new frames from
- * our client, which may be meta (WINDOWS_UPDATEs, PING, SETTINGS) or
- * new streams.
- *
- * As long as we have streams open in this session, we cannot really rest
- * since there are two conditions to wait on: 1. new data from the client,
- * 2. new data from the open streams to send back.
- *
- * Only when we have no more streams open, can we do a blocking read
- * on our connection.
- *
- * TODO: implement graceful GO_AWAY after configurable idle time
- */
- ap_update_child_status_from_conn(session->c->sbh, SERVER_BUSY_READ,
- session->c);
+ if (!h2_is_acceptable_connection(c, 1)) {
+ nghttp2_submit_goaway(session->ngh2, NGHTTP2_FLAG_NONE, 0,
+ NGHTTP2_INADEQUATE_SECURITY, NULL, 0);
+ }
- if (APLOGctrace2(session->c)) {
- ap_filter_t *filter = session->c->input_filters;
- while (filter) {
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, session->c,
- "h2_conn(%ld), has connection filter %s",
- session->id, filter->frec->name);
- filter = filter->next;
- }
- }
-
+ ap_update_child_status_from_conn(c->sbh, SERVER_BUSY_READ, c);
status = h2_session_start(session, &rv);
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, session->c,
"h2_session(%ld): starting on %s:%d", session->id,
- session->c->base_server->defn_name,
+ session->c->base_server->server_hostname,
session->c->local_addr->port);
if (status != APR_SUCCESS) {
h2_session_abort(session, status, rv);
- h2_session_destroy(session);
+ h2_session_eoc_callback(session);
return status;
}
- while (!h2_session_is_done(session)) {
- int have_written = 0;
- int have_read = 0;
- int got_streams;
-
- status = h2_session_write(session, wait_micros);
- if (status == APR_SUCCESS) {
- have_written = 1;
- wait_micros = 0;
- }
- else if (status == APR_EAGAIN) {
- /* nop */
- }
- else if (status == APR_TIMEUP) {
- wait_micros *= 2;
- if (wait_micros > MAX_WAIT_MICROS) {
- wait_micros = MAX_WAIT_MICROS;
- }
- }
- else {
- ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
- "h2_session(%ld): writing, terminating",
- session->id);
- h2_session_abort(session, status, 0);
- break;
- }
-
- /* We would like to do blocking reads as often as possible as they
- * are more efficient in regard to server resources.
- * We can do them under the following circumstances:
- * - we have no open streams and therefore have nothing to write
- * - we have just started the session and are waiting for the first
- * two frames to come in. There will always be at least 2 frames as
- * * h2 will send SETTINGS and SETTINGS-ACK
- * * h2c will count the header settings as one frame and we
- * submit our settings and need the ACK.
- */
- got_streams = !h2_stream_set_is_empty(session->streams);
- status = h2_session_read(session,
- (!got_streams
- || session->frames_received <= 1)?
- APR_BLOCK_READ : APR_NONBLOCK_READ);
- switch (status) {
- case APR_SUCCESS: /* successful read, reset our idle timers */
- have_read = 1;
- wait_micros = 0;
- break;
- case APR_EAGAIN: /* non-blocking read, nothing there */
- break;
- case APR_EBADF: /* connection is not there any more */
- case APR_EOF:
- case APR_ECONNABORTED:
- case APR_ECONNRESET:
- case APR_TIMEUP: /* blocked read, timed out */
- ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
- "h2_session(%ld): reading",
- session->id);
- h2_session_abort(session, status, 0);
- break;
- default:
- ap_log_cerror( APLOG_MARK, APLOG_INFO, status, session->c,
- APLOGNO(02950)
- "h2_session(%ld): error reading, terminating",
- session->id);
- h2_session_abort(session, status, 0);
- break;
- }
-
- if (!have_read && !have_written
- && !h2_stream_set_is_empty(session->streams)) {
- /* Nothing to read or write, we have streams, but
- * the have no data yet ready to be delivered. Slowly
- * back off to give others a chance to do their work.
- */
- if (wait_micros == 0) {
- wait_micros = 10;
- }
- }
- }
-
+ status = h2_session_process(session);
+
ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
"h2_session(%ld): done", session->id);
-
- ap_update_child_status_from_conn(session->c->sbh, SERVER_CLOSING,
- session->c);
-
h2_session_close(session);
- h2_session_destroy(session);
+ h2_session_flush(session);
+ /* hereafter session might be gone */
- return DONE;
+ /* Make sure this connection gets closed properly. */
+ ap_update_child_status_from_conn(c->sbh, SERVER_CLOSING, c);
+ c->keepalive = AP_CONN_CLOSE;
+ if (c->cs) {
+ c->cs->state = CONN_STATE_WRITE_COMPLETION;
+ }
+
+ return status;
}
static void fix_event_conn(conn_rec *c, conn_rec *master);
-/*
- * We would like to create the connection more lightweight like
- * slave connections in 2.5-DEV. But we get 500 responses on long
- * cgi tests in modules/h2.t as the script parsing seems to see an
- * EOF from the cgi before anything is sent.
- *
-conn_rec *h2_conn_create(conn_rec *master, apr_pool_t *pool)
-{
- conn_rec *c = (conn_rec *) apr_palloc(pool, sizeof(conn_rec));
-
- memcpy(c, master, sizeof(conn_rec));
- c->id = (master->id & (long)pool);
- c->slaves = NULL;
- c->master = master;
- c->input_filters = NULL;
- c->output_filters = NULL;
- c->pool = pool;
-
- return c;
-}
-*/
+static int SLAVE_CONN_25DEV_STYLE = 1;
conn_rec *h2_conn_create(conn_rec *master, apr_pool_t *pool)
{
@@ -368,39 +202,56 @@ conn_rec *h2_conn_create(conn_rec *maste
conn_rec *c;
AP_DEBUG_ASSERT(master);
-
- /* CAVEAT: it seems necessary to setup the conn_rec in the master
- * connection thread. Other attempts crashed.
- * HOWEVER: we setup the connection using the pools and other items
- * from the master connection, since we do not want to allocate
- * lots of resources here.
- * Lets allocated pools and everything else when we actually start
- * working on this new connection.
- */
- /* Not sure about the scoreboard handle. Reusing the one from the main
- * connection could make sense, is not really correct, but we cannot
- * easily create new handles for our worker threads either.
- * TODO
- */
- socket = ap_get_module_config(master->conn_config, &core_module);
- c = ap_run_create_connection(pool, master->base_server,
- socket,
- master->id^((long)pool),
- master->sbh,
- master->bucket_alloc);
+
+ if (SLAVE_CONN_25DEV_STYLE) {
+ /* This is like the slave connection creation from 2.5-DEV. A
+ * very efficient way - not sure how compatible this is, since
+ * the core hooks are no longer run.
+ * But maybe it's is better this way, not sure yet.
+ */
+ c = (conn_rec *) apr_palloc(pool, sizeof(conn_rec));
+
+ memcpy(c, master, sizeof(conn_rec));
+ c->id = (master->id & (long)pool);
+ c->master = master;
+ c->input_filters = NULL;
+ c->output_filters = NULL;
+ c->pool = pool;
+ }
+ else {
+ /* CAVEAT: it seems necessary to setup the conn_rec in the master
+ * connection thread. Other attempts crashed.
+ * HOWEVER: we setup the connection using the pools and other items
+ * from the master connection, since we do not want to allocate
+ * lots of resources here.
+ * Lets allocated pools and everything else when we actually start
+ * working on this new connection.
+ */
+ /* Not sure about the scoreboard handle. Reusing the one from the main
+ * connection could make sense, is not really correct, but we cannot
+ * easily create new handles for our worker threads either.
+ * TODO
+ */
+ socket = ap_get_module_config(master->conn_config, &core_module);
+ c = ap_run_create_connection(pool, master->base_server,
+ socket,
+ master->id^((long)pool),
+ master->sbh,
+ master->bucket_alloc);
+ }
if (c == NULL) {
ap_log_perror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, pool,
APLOGNO(02913) "h2_task: creating conn");
- return NULL;
}
return c;
}
-apr_status_t h2_conn_setup(h2_task_env *env, struct h2_worker *worker)
+apr_status_t h2_conn_setup(h2_task *task, apr_bucket_alloc_t *bucket_alloc,
+ apr_thread_t *thread, apr_socket_t *socket)
{
- conn_rec *master = env->mplx->c;
+ conn_rec *master = task->mplx->c;
- ap_log_perror(APLOG_MARK, APLOG_TRACE3, 0, env->pool,
+ ap_log_perror(APLOG_MARK, APLOG_TRACE3, 0, task->pool,
"h2_conn(%ld): created from master", master->id);
/* Ok, we are just about to start processing the connection and
@@ -409,28 +260,17 @@ apr_status_t h2_conn_setup(h2_task_env *
* sub-resources from it, so that we get a nice reuse of
* pools.
*/
- env->c.pool = env->pool;
- env->c.bucket_alloc = h2_worker_get_bucket_alloc(worker);
- env->c.current_thread = h2_worker_get_thread(worker);
+ task->c->pool = task->pool;
+ task->c->current_thread = thread;
+ task->c->bucket_alloc = bucket_alloc;
- env->c.conn_config = ap_create_conn_config(env->pool);
- env->c.notes = apr_table_make(env->pool, 5);
+ task->c->conn_config = ap_create_conn_config(task->pool);
+ task->c->notes = apr_table_make(task->pool, 5);
- ap_set_module_config(env->c.conn_config, &core_module,
- h2_worker_get_socket(worker));
+ /* In order to do this in 2.4.x, we need to add a member to conn_rec */
+ task->c->master = master;
- /* If we serve http:// requests over a TLS connection, we do
- * not want any mod_ssl vars to be visible.
- */
- if (ssl_module && (!env->scheme || strcmp("http", env->scheme))) {
- /* See #19, there is a range of SSL variables to be gotten from
- * the main connection that should be available in request handlers
- */
- void *sslcfg = ap_get_module_config(master->conn_config, ssl_module);
- if (sslcfg) {
- ap_set_module_config(env->c.conn_config, ssl_module, sslcfg);
- }
- }
+ ap_set_module_config(task->c->conn_config, &core_module, socket);
/* This works for mpm_worker so far. Other mpm modules have
* different needs, unfortunately. The most interesting one
@@ -441,7 +281,7 @@ apr_status_t h2_conn_setup(h2_task_env *
/* all fine */
break;
case H2_MPM_EVENT:
- fix_event_conn(&env->c, master);
+ fix_event_conn(task->c, master);
break;
default:
/* fingers crossed */
@@ -453,26 +293,7 @@ apr_status_t h2_conn_setup(h2_task_env *
* 400 Bad Request
* when names do not match. We prefer a predictable 421 status.
*/
- env->c.keepalives = 1;
-
- return APR_SUCCESS;
-}
-
-apr_status_t h2_conn_post(conn_rec *c, h2_worker *worker)
-{
- (void)worker;
-
- /* be sure no one messes with this any more */
- memset(c, 0, sizeof(*c));
- return APR_SUCCESS;
-}
-
-apr_status_t h2_conn_process(conn_rec *c, apr_socket_t *socket)
-{
- AP_DEBUG_ASSERT(c);
-
- c->clogging_input_filters = 1;
- ap_process_connection(c, socket);
+ task->c->keepalives = 1;
return APR_SUCCESS;
}
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h Fri Nov 20 15:13:11 2015
@@ -17,20 +17,16 @@
#define __mod_h2__h2_conn__
struct h2_task;
-struct h2_task_env;
-struct h2_worker;
-/* Process the connection that is now starting the HTTP/2
+/**
+ * Process the connection that is now starting the HTTP/2
* conversation. Return when the HTTP/2 session is done
* and the connection will close.
+ *
+ * @param c the connection HTTP/2 is starting on
+ * @param r the upgrad requestion that still awaits an answer, optional
*/
-apr_status_t h2_conn_main(conn_rec *c);
-
-/* Process the request that has been upgraded to a HTTP/2
- * conversation. Return when the HTTP/2 session is done
- * and the connection will close.
- */
-apr_status_t h2_conn_rprocess(request_rec *r);
+apr_status_t h2_conn_process(conn_rec *c, request_rec *r);
/* Initialize this child process for h2 connection work,
* to be called once during child init before multi processing
@@ -52,9 +48,7 @@ h2_mpm_type_t h2_conn_mpm_type(void);
conn_rec *h2_conn_create(conn_rec *master, apr_pool_t *stream_pool);
-apr_status_t h2_conn_setup(struct h2_task_env *env, struct h2_worker *worker);
-apr_status_t h2_conn_post(conn_rec *c, struct h2_worker *worker);
-
-apr_status_t h2_conn_process(conn_rec *c, apr_socket_t *socket);
+apr_status_t h2_conn_setup(struct h2_task *task, apr_bucket_alloc_t *bucket_alloc,
+ apr_thread_t *thread, apr_socket_t *socket);
#endif /* defined(__mod_h2__h2_conn__) */
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c Fri Nov 20 15:13:11 2015
@@ -28,31 +28,33 @@
#include "h2_h2.h"
#include "h2_util.h"
-#define WRITE_BUFFER_SIZE (64*1024)
+#define TLS_DATA_MAX (16*1024)
+
+/* Calculated like this: assuming MTU 1500 bytes
+ * 1500 - 40 (IP) - 20 (TCP) - 40 (TCP options)
+ * - TLS overhead (60-100)
+ * ~= 1300 bytes */
#define WRITE_SIZE_INITIAL 1300
-#define WRITE_SIZE_MAX (16*1024)
-#define WRITE_SIZE_IDLE_USEC (1*APR_USEC_PER_SEC)
-#define WRITE_SIZE_THRESHOLD (1*1024*1024)
+/* Calculated like this: max TLS record size 16*1024
+ * - 40 (IP) - 20 (TCP) - 40 (TCP options)
+ * - TLS overhead (60-100)
+ * which seems to create less TCP packets overall
+ */
+#define WRITE_SIZE_MAX (TLS_DATA_MAX - 100)
+
+#define WRITE_BUFFER_SIZE (8*WRITE_SIZE_MAX)
apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c)
{
- io->connection = c;
- io->input = apr_brigade_create(c->pool, c->bucket_alloc);
- io->output = apr_brigade_create(c->pool, c->bucket_alloc);
- io->buflen = 0;
- /* That is where we start with,
- * see https://issues.apache.org/jira/browse/TS-2503 */
- io->write_size = WRITE_SIZE_INITIAL;
- io->last_write = 0;
- io->buffer_output = h2_h2_is_tls(c);
-
- /* Currently we buffer only for TLS output. The reason this gives
- * improved performance is that buckets send to the mod_ssl network
- * filter will be encrypted in chunks. There is a special filter
- * that tries to aggregate data, but that does not work well when
- * bucket sizes alternate between tiny frame headers and large data
- * chunks.
- */
+ h2_config *cfg = h2_config_get(c);
+
+ io->connection = c;
+ io->input = apr_brigade_create(c->pool, c->bucket_alloc);
+ io->output = apr_brigade_create(c->pool, c->bucket_alloc);
+ io->buflen = 0;
+ io->is_tls = h2_h2_is_tls(c);
+ io->buffer_output = io->is_tls;
+
if (io->buffer_output) {
io->bufsize = WRITE_BUFFER_SIZE;
io->buffer = apr_pcalloc(c->pool, io->bufsize);
@@ -61,13 +63,33 @@ apr_status_t h2_conn_io_init(h2_conn_io
io->bufsize = 0;
}
+ if (io->is_tls) {
+ /* That is where we start with,
+ * see https://issues.apache.org/jira/browse/TS-2503 */
+ io->warmup_size = h2_config_geti64(cfg, H2_CONF_TLS_WARMUP_SIZE);
+ io->cooldown_usecs = (h2_config_geti(cfg, H2_CONF_TLS_COOLDOWN_SECS)
+ * APR_USEC_PER_SEC);
+ io->write_size = WRITE_SIZE_INITIAL;
+ }
+ else {
+ io->warmup_size = 0;
+ io->cooldown_usecs = 0;
+ io->write_size = io->bufsize;
+ }
+
+ if (APLOGctrace1(c)) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
+ "h2_conn_io(%ld): init, buffering=%d, warmup_size=%ld, cd_secs=%f",
+ io->connection->id, io->buffer_output, (long)io->warmup_size,
+ ((float)io->cooldown_usecs/APR_USEC_PER_SEC));
+ }
+
return APR_SUCCESS;
}
-void h2_conn_io_destroy(h2_conn_io *io)
+int h2_conn_io_is_buffered(h2_conn_io *io)
{
- io->input = NULL;
- io->output = NULL;
+ return io->bufsize > 0;
}
static apr_status_t h2_conn_io_bucket_read(h2_conn_io *io,
@@ -159,7 +181,7 @@ apr_status_t h2_conn_io_read(h2_conn_io
status = ap_get_brigade(io->connection->input_filters,
io->input, AP_MODE_READBYTES,
- block, 16 * 4096);
+ block, 64 * 4096);
switch (status) {
case APR_SUCCESS:
return h2_conn_io_bucket_read(io, block, on_read_cb, puser, &done);
@@ -174,15 +196,22 @@ apr_status_t h2_conn_io_read(h2_conn_io
return status;
}
-static apr_status_t flush_out(apr_bucket_brigade *bb, void *ctx)
+static apr_status_t pass_out(apr_bucket_brigade *bb, void *ctx)
{
h2_conn_io *io = (h2_conn_io*)ctx;
apr_status_t status;
apr_off_t bblen;
+ if (APR_BRIGADE_EMPTY(bb)) {
+ return APR_SUCCESS;
+ }
+
ap_update_child_status(io->connection->sbh, SERVER_BUSY_WRITE, NULL);
- status = apr_brigade_length(bb, 1, &bblen);
+ status = apr_brigade_length(bb, 0, &bblen);
if (status == APR_SUCCESS) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
+ "h2_conn_io(%ld): pass_out brigade %ld bytes",
+ io->connection->id, (long)bblen);
status = ap_pass_brigade(io->connection->output_filters, bb);
if (status == APR_SUCCESS) {
io->bytes_written += (apr_size_t)bblen;
@@ -193,14 +222,18 @@ static apr_status_t flush_out(apr_bucket
return status;
}
+/* Bring the current buffer content into the output brigade, appropriately
+ * chunked.
+ */
static apr_status_t bucketeer_buffer(h2_conn_io *io) {
const char *data = io->buffer;
apr_size_t remaining = io->buflen;
apr_bucket *b;
int bcount, i;
- if (io->write_size > WRITE_SIZE_INITIAL
- && (apr_time_now() - io->last_write) >= WRITE_SIZE_IDLE_USEC) {
+ if (io->write_size > WRITE_SIZE_INITIAL
+ && (io->cooldown_usecs > 0)
+ && (apr_time_now() - io->last_write) >= io->cooldown_usecs) {
/* long time not written, reset write size */
io->write_size = WRITE_SIZE_INITIAL;
io->bytes_written = 0;
@@ -209,7 +242,7 @@ static apr_status_t bucketeer_buffer(h2_
(long)io->connection->id, (long)io->write_size);
}
else if (io->write_size < WRITE_SIZE_MAX
- && io->bytes_written >= WRITE_SIZE_THRESHOLD) {
+ && io->bytes_written >= io->warmup_size) {
/* connection is hot, use max size */
io->write_size = WRITE_SIZE_MAX;
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection,
@@ -238,16 +271,22 @@ apr_status_t h2_conn_io_write(h2_conn_io
const char *buf, size_t length)
{
apr_status_t status = APR_SUCCESS;
- io->unflushed = 1;
- if (io->buffer_output) {
+ io->unflushed = 1;
+ if (io->bufsize > 0) {
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
"h2_conn_io: buffering %ld bytes", (long)length);
+
+ if (!APR_BRIGADE_EMPTY(io->output)) {
+ status = h2_conn_io_pass(io);
+ io->unflushed = 1;
+ }
+
while (length > 0 && (status == APR_SUCCESS)) {
apr_size_t avail = io->bufsize - io->buflen;
if (avail <= 0) {
bucketeer_buffer(io);
- status = flush_out(io->output, io);
+ status = pass_out(io->output, io);
io->buflen = 0;
}
else if (length > avail) {
@@ -266,47 +305,78 @@ apr_status_t h2_conn_io_write(h2_conn_io
}
else {
- status = apr_brigade_write(io->output, flush_out, io, buf, length);
- if (status != APR_SUCCESS) {
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, io->connection,
- "h2_conn_io: write error");
- }
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, io->connection,
+ "h2_conn_io: writing %ld bytes to brigade", (long)length);
+ status = apr_brigade_write(io->output, pass_out, io, buf, length);
}
return status;
}
+apr_status_t h2_conn_io_writeb(h2_conn_io *io, apr_bucket *b)
+{
+ APR_BRIGADE_INSERT_TAIL(io->output, b);
+ io->unflushed = 1;
+ return APR_SUCCESS;
+}
-apr_status_t h2_conn_io_flush(h2_conn_io *io)
+apr_status_t h2_conn_io_consider_flush(h2_conn_io *io)
{
+ apr_status_t status = APR_SUCCESS;
+
+ /* The HTTP/1.1 network output buffer/flush behaviour does not
+ * give optimal performance in the HTTP/2 case, as the pattern of
+ * buckets (data/eor/eos) is different.
+ * As long as we have not found out the "best" way to deal with
+ * this, force a flush at least every WRITE_BUFFER_SIZE amount
+ * of data.
+ */
if (io->unflushed) {
- apr_status_t status;
+ apr_off_t len = 0;
+ if (!APR_BRIGADE_EMPTY(io->output)) {
+ apr_brigade_length(io->output, 0, &len);
+ }
+ len += io->buflen;
+ if (len >= WRITE_BUFFER_SIZE) {
+ return h2_conn_io_pass(io);
+ }
+ }
+ return status;
+}
+
+static apr_status_t h2_conn_io_flush_int(h2_conn_io *io, int force)
+{
+ if (io->unflushed || force) {
if (io->buflen > 0) {
+ /* something in the buffer, put it in the output brigade */
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection,
"h2_conn_io: flush, flushing %ld bytes", (long)io->buflen);
bucketeer_buffer(io);
io->buflen = 0;
}
- /* Append flush.
- */
- APR_BRIGADE_INSERT_TAIL(io->output,
- apr_bucket_flush_create(io->output->bucket_alloc));
-
- /* Send it out through installed filters (TLS) to the client */
- status = flush_out(io->output, io);
- if (status == APR_SUCCESS) {
- /* These are all fine and no reason for concern. Everything else
- * is interesting. */
- io->unflushed = 0;
- }
- else {
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, io->connection,
- "h2_conn_io: flush error");
+ if (force) {
+ APR_BRIGADE_INSERT_TAIL(io->output,
+ apr_bucket_flush_create(io->output->bucket_alloc));
}
- return status;
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection,
+ "h2_conn_io: flush");
+ /* Send it out */
+ io->unflushed = 0;
+ return pass_out(io->output, io);
+ /* no more access after this, as we might have flushed an EOC bucket
+ * that de-allocated us all. */
}
return APR_SUCCESS;
}
+apr_status_t h2_conn_io_flush(h2_conn_io *io)
+{
+ return h2_conn_io_flush_int(io, 1);
+}
+
+apr_status_t h2_conn_io_pass(h2_conn_io *io)
+{
+ return h2_conn_io_flush_int(io, 0);
+}
\ No newline at end of file
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.h?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.h Fri Nov 20 15:13:11 2015
@@ -26,11 +26,16 @@ typedef struct {
conn_rec *connection;
apr_bucket_brigade *input;
apr_bucket_brigade *output;
- int buffer_output;
- int write_size;
+
+ int is_tls;
+ apr_time_t cooldown_usecs;
+ apr_int64_t warmup_size;
+
+ apr_size_t write_size;
apr_time_t last_write;
- apr_size_t bytes_written;
+ apr_int64_t bytes_written;
+ int buffer_output;
char *buffer;
apr_size_t buflen;
apr_size_t bufsize;
@@ -38,7 +43,8 @@ typedef struct {
} h2_conn_io;
apr_status_t h2_conn_io_init(h2_conn_io *io, conn_rec *c);
-void h2_conn_io_destroy(h2_conn_io *io);
+
+int h2_conn_io_is_buffered(h2_conn_io *io);
typedef apr_status_t (*h2_conn_io_on_read_cb)(const char *data, apr_size_t len,
apr_size_t *readlen, int *done,
@@ -52,7 +58,12 @@ apr_status_t h2_conn_io_read(h2_conn_io
apr_status_t h2_conn_io_write(h2_conn_io *io,
const char *buf,
size_t length);
+
+apr_status_t h2_conn_io_writeb(h2_conn_io *io, apr_bucket *b);
+
+apr_status_t h2_conn_io_consider_flush(h2_conn_io *io);
+apr_status_t h2_conn_io_pass(h2_conn_io *io);
apr_status_t h2_conn_io_flush(h2_conn_io *io);
#endif /* defined(__mod_h2__h2_conn_io__) */
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.c?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.c Fri Nov 20 15:13:11 2015
@@ -32,11 +32,11 @@ static h2_ctx *h2_ctx_create(const conn_
return ctx;
}
-h2_ctx *h2_ctx_create_for(const conn_rec *c, h2_task_env *env)
+h2_ctx *h2_ctx_create_for(const conn_rec *c, h2_task *task)
{
h2_ctx *ctx = h2_ctx_create(c);
if (ctx) {
- ctx->task_env = env;
+ ctx->task = task;
}
return ctx;
}
@@ -76,7 +76,7 @@ h2_ctx *h2_ctx_server_set(h2_ctx *ctx, s
int h2_ctx_is_task(h2_ctx *ctx)
{
- return ctx && !!ctx->task_env;
+ return ctx && !!ctx->task;
}
int h2_ctx_is_active(h2_ctx *ctx)
@@ -84,7 +84,7 @@ int h2_ctx_is_active(h2_ctx *ctx)
return ctx && ctx->is_h2;
}
-struct h2_task_env *h2_ctx_get_task(h2_ctx *ctx)
+struct h2_task *h2_ctx_get_task(h2_ctx *ctx)
{
- return ctx->task_env;
+ return ctx->task;
}
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.h?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_ctx.h Fri Nov 20 15:13:11 2015
@@ -16,7 +16,7 @@
#ifndef __mod_h2__h2_ctx__
#define __mod_h2__h2_ctx__
-struct h2_task_env;
+struct h2_task;
struct h2_config;
/**
@@ -30,7 +30,7 @@ struct h2_config;
typedef struct h2_ctx {
int is_h2; /* h2 engine is used */
const char *protocol; /* the protocol negotiated */
- struct h2_task_env *task_env; /* the h2_task environment or NULL */
+ struct h2_task *task; /* the h2_task executing or NULL */
const char *hostname; /* hostname negotiated via SNI, optional */
server_rec *server; /* httpd server config selected. */
struct h2_config *config; /* effective config in this context */
@@ -38,7 +38,7 @@ typedef struct h2_ctx {
h2_ctx *h2_ctx_get(const conn_rec *c);
h2_ctx *h2_ctx_rget(const request_rec *r);
-h2_ctx *h2_ctx_create_for(const conn_rec *c, struct h2_task_env *env);
+h2_ctx *h2_ctx_create_for(const conn_rec *c, struct h2_task *task);
/* Set the h2 protocol established on this connection context or
@@ -58,6 +58,6 @@ const char *h2_ctx_protocol_get(const co
int h2_ctx_is_task(h2_ctx *ctx);
int h2_ctx_is_active(h2_ctx *ctx);
-struct h2_task_env *h2_ctx_get_task(h2_ctx *ctx);
+struct h2_task *h2_ctx_get_task(h2_ctx *ctx);
#endif /* defined(__mod_h2__h2_ctx__) */
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c Fri Nov 20 15:13:11 2015
@@ -59,11 +59,6 @@ apr_status_t h2_from_h1_destroy(h2_from_
return APR_SUCCESS;
}
-h2_from_h1_state_t h2_from_h1_get_state(h2_from_h1 *from_h1)
-{
- return from_h1->state;
-}
-
static void set_state(h2_from_h1 *from_h1, h2_from_h1_state_t state)
{
if (from_h1->state != state) {
@@ -78,16 +73,9 @@ h2_response *h2_from_h1_get_response(h2_
static apr_status_t make_h2_headers(h2_from_h1 *from_h1, request_rec *r)
{
- from_h1->response = h2_response_create(from_h1->stream_id,
- from_h1->status, from_h1->hlines,
- from_h1->pool);
- if (from_h1->response == NULL) {
- ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EINVAL, r->connection,
- APLOGNO(02915)
- "h2_from_h1(%d): unable to create resp_head",
- from_h1->stream_id);
- return APR_EINVAL;
- }
+ from_h1->response = h2_response_create(from_h1->stream_id, 0,
+ from_h1->http_status, from_h1->hlines,
+ from_h1->pool);
from_h1->content_length = from_h1->response->content_length;
from_h1->chunked = r->chunked;
@@ -202,8 +190,7 @@ apr_status_t h2_from_h1_read_response(h2
}
if (from_h1->state == H2_RESP_ST_STATUS_LINE) {
/* instead of parsing, just take it directly */
- from_h1->status = apr_psprintf(from_h1->pool,
- "%d", f->r->status);
+ from_h1->http_status = f->r->status;
from_h1->state = H2_RESP_ST_HEADERS;
}
else if (line[0] == '\0') {
@@ -417,7 +404,7 @@ static h2_response *create_response(h2_f
}
if (!apr_is_empty_array(r->content_languages)) {
- int i;
+ unsigned int i;
char *token;
char **languages = (char **)(r->content_languages->elts);
const char *field = apr_table_get(r->headers_out, "Content-Language");
@@ -492,8 +479,8 @@ static h2_response *create_response(h2_f
apr_status_t h2_response_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
{
- h2_task_env *env = f->ctx;
- h2_from_h1 *from_h1 = env->output? env->output->from_h1 : NULL;
+ h2_task *task = f->ctx;
+ h2_from_h1 *from_h1 = task->output? task->output->from_h1 : NULL;
request_rec *r = f->r;
apr_bucket *b;
ap_bucket_error *eb = NULL;
@@ -503,7 +490,7 @@ apr_status_t h2_response_output_filter(a
ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, f->c,
"h2_from_h1(%d): output_filter called", from_h1->stream_id);
- if (r->header_only && env->output && from_h1->response) {
+ if (r->header_only && task->output && from_h1->response) {
/* throw away any data after we have compiled the response */
apr_brigade_cleanup(bb);
return OK;
Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.h?rev=1715371&r1=1715370&r2=1715371&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.h Fri Nov 20 15:13:11 2015
@@ -48,35 +48,25 @@ struct h2_from_h1 {
apr_pool_t *pool;
apr_bucket_brigade *bb;
- apr_size_t content_length;
+ apr_off_t content_length;
int chunked;
- const char *status;
+ int http_status;
apr_array_header_t *hlines;
struct h2_response *response;
};
-typedef void h2_from_h1_state_change_cb(struct h2_from_h1 *resp,
- h2_from_h1_state_t prevstate,
- void *cb_ctx);
-
h2_from_h1 *h2_from_h1_create(int stream_id, apr_pool_t *pool);
apr_status_t h2_from_h1_destroy(h2_from_h1 *response);
-void h2_from_h1_set_state_change_cb(h2_from_h1 *from_h1,
- h2_from_h1_state_change_cb *callback,
- void *cb_ctx);
-
apr_status_t h2_from_h1_read_response(h2_from_h1 *from_h1,
ap_filter_t* f, apr_bucket_brigade* bb);
struct h2_response *h2_from_h1_get_response(h2_from_h1 *from_h1);
-h2_from_h1_state_t h2_from_h1_get_state(h2_from_h1 *from_h1);
-
apr_status_t h2_response_output_filter(ap_filter_t *f, apr_bucket_brigade *bb);
#endif /* defined(__mod_h2__h2_from_h1__) */