1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
/* 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.
*/
#ifndef __mod_h2__h2_push__
#define __mod_h2__h2_push__
#include <http_protocol.h>
#include "h2.h"
#include "h2_headers.h"
struct h2_request;
struct h2_ngheader;
struct h2_session;
struct h2_stream;
typedef struct h2_push {
const struct h2_request *req;
h2_priority *priority;
} h2_push;
typedef enum {
H2_PUSH_DIGEST_APR_HASH,
H2_PUSH_DIGEST_SHA256
} h2_push_digest_type;
/*******************************************************************************
* 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,
* - with openssl, it uses SHA256 to calculate the hash value, otherwise it
* falls back to apr_hashfunc_default()
* - 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.
* - While useful by itself to avoid duplicated PUSHes on the same connection,
* the original idea was that clients provided a 'Cache-Digest' header with
* the values of *their own* cached resources. This was described in
* <https://datatracker.ietf.org/doc/draft-kazuho-h2-cache-digest/>
* and some subsequent revisions that tweaked values but kept the overall idea.
* - The draft was abandoned by the IETF http-wg, as support from major clients,
* e.g. browsers, was lacking for various reasons.
* - For these reasons, mod_h2 abandoned its support for client supplied values
* but keeps the diary. It seems to provide value for applications using PUSH,
* is configurable in size and defaults to a very moderate amount of memory
* used.
* - 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 push diary is based on the abandoned draft
* <https://datatracker.ietf.org/doc/draft-kazuho-h2-cache-digest/>
* that describes how to use golomb filters.
*/
typedef struct h2_push_diary h2_push_diary;
typedef void h2_push_digest_calc(h2_push_diary *diary, apr_uint64_t *phash, h2_push *push);
struct h2_push_diary {
apr_array_header_t *entries;
int NMax; /* Maximum for N, should size change be necessary */
int N; /* Current maximum number of entries, power of 2 */
apr_uint64_t mask; /* mask for relevant bits */
unsigned int mask_bits; /* number of relevant bits */
const char *authority;
h2_push_digest_type dtype;
h2_push_digest_calc *dcalc;
};
/**
* Determine the list of h2_push'es to send to the client on behalf of
* the given request/response pair.
*
* @param p the pool to use
* @param req the requst from the client
* @param res the response from the server
* @return array of h2_push addresses or NULL
*/
#if AP_HAS_RESPONSE_BUCKETS
apr_array_header_t *h2_push_collect(apr_pool_t *p,
const struct h2_request *req,
apr_uint32_t push_policy,
const ap_bucket_response *res);
#else
apr_array_header_t *h2_push_collect(apr_pool_t *p,
const struct h2_request *req,
apr_uint32_t push_policy,
const struct h2_headers *res);
#endif
/**
* Create a new push diary for the given maximum number of entries.
*
* @param p the pool to use
* @param N the max number of entries, rounded up to 2^x
* @return the created diary, might be NULL of max_entries is 0
*/
h2_push_diary *h2_push_diary_create(apr_pool_t *p, int N);
/**
* Filters the given pushes against the diary and returns only those pushes
* that were newly entered in the diary.
*/
apr_array_header_t *h2_push_diary_update(struct h2_session *session, apr_array_header_t *pushes);
/**
* Collect pushes for the given request/response pair, enter them into the
* diary and return those pushes newly entered.
*/
#if AP_HAS_RESPONSE_BUCKETS
apr_array_header_t *h2_push_collect_update(struct h2_stream *stream,
const struct h2_request *req,
const ap_bucket_response *res);
#else
apr_array_header_t *h2_push_collect_update(struct h2_stream *stream,
const struct h2_request *req,
const struct h2_headers *res);
#endif
/**
* Get a cache digest as described in
* https://datatracker.ietf.org/doc/draft-kazuho-h2-cache-digest/
* from the contents of the push diary.
*
* @param diary the diary to calculdate the digest from
* @param p the pool to use
* @param authority the authority to get the data for, use NULL/"*" for all
* @param pdata on successful return, the binary cache digest
* @param plen on successful return, the length of the binary data
*/
apr_status_t h2_push_diary_digest_get(h2_push_diary *diary, apr_pool_t *p,
int maxP, const char *authority,
const char **pdata, apr_size_t *plen);
#endif /* defined(__mod_h2__h2_push__) */
|