/*******************************************************************************
* push diary
+ *
+ * - The push diary keeps track of resources already PUSHed via HTTP/2 on this
+ * connection. It records a hash value from the absolute URL of the resource
+ * pushed.
+ * - Lacking openssl, it uses 'apr_hashfunc_default' for the value
+ * - with openssl, it uses SHA256 to calculate the hash value
+ * - whatever the method to generate the hash, the diary keeps a maximum of 64
+ * bits per hash, limiting the memory consumption to about
+ * H2PushDiarySize * 8
+ * bytes. Entries are sorted by most recently used and oldest entries are
+ * forgotten first.
+ * - Clients can initialize/replace the push diary by sending a 'Cache-Digest'
+ * header. Currently, this is the base64url encoded value of the cache digest
+ * as specified in https://datatracker.ietf.org/doc/draft-kazuho-h2-cache-digest/
+ * This draft can be expected to evolve and the definition of the header
+ * will be added there and refined.
+ * - The cache digest header is a Golomb Coded Set of hash values, but it may
+ * limit the amount of bits per hash value even further. For a good description
+ * of GCS, read here:
+ * http://giovanni.bajo.it/post/47119962313/golomb-coded-sets-smaller-than-bloom-filters
+ * - The means that the push diary might be initialized with hash values of much
+ * less than 64 bits, leading to more false positives, but smaller digest size.
******************************************************************************/
#include <apr_base64.h>
#include <apr_strings.h>
+#include <ap_mpm.h>
+
#include <httpd.h>
#include <http_core.h>
#include <http_config.h>
{
apr_status_t status = APR_SUCCESS;
conn_rec *c = session->c;
- int rv, have_written, have_read;
+ int rv, have_written, have_read, mpm_state;
ap_log_cerror( APLOG_MARK, APLOG_TRACE1, status, c,
"h2_session(%ld): process start, async=%d", session->id, async);
break;
case H2_SESSION_ST_IDLE:
+ if ((status = ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state))) {
+ goto out;
+ }
+ if (mpm_state == AP_MPMQ_STOPPING) {
+ dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, 0, NULL);
+ break;
+ }
+ /* We'd like to wait in smaller increments, using a 1 second
+ * timeout maybe, trying n times. That would allow us to exit
+ * on MPMQ_STOPPING earlier.
+ * Unfortunately, once a socket timeout happened, SSL reports
+ * EOF on reads and the connection is gone. Not sure if we can
+ * avoid that...
+ */
h2_filter_cin_timeout_set(session->cin, session->keepalive_secs);
ap_update_child_status(c->sbh, SERVER_BUSY_KEEPALIVE, NULL);
status = h2_session_read(session, 1, 10);
}
else if (APR_STATUS_IS_TIMEUP(status)) {
dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, 0, NULL);
- break;
}
else {
dispatch_event(session, H2_SESSION_EV_CONN_ERROR, 0, NULL);