* 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 pdata on successful return, the binary cache digest * @param plen on successful return, the length of the binary data */
| 804 | * @param plen on successful return, the length of the binary data |
| 805 | */ |
| 806 | apr_status_t h2_push_diary_digest_get(h2_push_diary *diary, apr_pool_t *pool, |
| 807 | int maxP, const char *authority, |
| 808 | const char **pdata, apr_size_t *plen) |
| 809 | { |
| 810 | int nelts, N; |
| 811 | unsigned char log2n, log2pmax; |
| 812 | gset_encoder encoder; |
| 813 | apr_uint64_t *hashes; |
| 814 | apr_size_t hash_count, i; |
| 815 | |
| 816 | nelts = diary->entries->nelts; |
| 817 | N = ceil_power_of_2(nelts); |
| 818 | log2n = h2_log2(N); |
| 819 | |
| 820 | /* Now log2p is the max number of relevant bits, so that |
| 821 | * log2p + log2n == mask_bits. We can use a lower log2p |
| 822 | * and have a shorter set encoding... |
| 823 | */ |
| 824 | log2pmax = h2_log2(ceil_power_of_2(maxP)); |
| 825 | |
| 826 | memset(&encoder, 0, sizeof(encoder)); |
| 827 | encoder.diary = diary; |
| 828 | encoder.log2p = H2MIN(diary->mask_bits - log2n, log2pmax); |
| 829 | encoder.mask_bits = log2n + encoder.log2p; |
| 830 | encoder.delta_bits = diary->mask_bits - encoder.mask_bits; |
| 831 | encoder.fixed_bits = encoder.log2p; |
| 832 | encoder.fixed_mask = 1; |
| 833 | encoder.fixed_mask = (encoder.fixed_mask << encoder.fixed_bits) - 1; |
| 834 | encoder.pool = pool; |
| 835 | encoder.datalen = 512; |
| 836 | encoder.data = apr_pcalloc(encoder.pool, encoder.datalen); |
| 837 | |
| 838 | encoder.data[0] = log2n; |
| 839 | encoder.data[1] = encoder.log2p; |
| 840 | encoder.offset = 1; |
| 841 | encoder.bit = 8; |
| 842 | encoder.last = 0; |
| 843 | |
| 844 | /* Intentional no APLOGNO */ |
| 845 | ap_log_perror(APLOG_MARK, GCSLOG_LEVEL, 0, pool, |
| 846 | "h2_push_diary_digest_get: %d entries, N=%d, log2n=%d, " |
| 847 | "mask_bits=%d, enc.mask_bits=%d, delta_bits=%d, enc.log2p=%d, authority=%s", |
| 848 | (int)nelts, (int)N, (int)log2n, diary->mask_bits, |
| 849 | (int)encoder.mask_bits, (int)encoder.delta_bits, |
| 850 | (int)encoder.log2p, authority); |
| 851 | |
| 852 | if (!authority || !diary->authority |
| 853 | || !strcmp("*", authority) || !strcmp(diary->authority, authority)) { |
| 854 | hash_count = diary->entries->nelts; |
| 855 | hashes = apr_pcalloc(encoder.pool, hash_count); |
| 856 | for (i = 0; i < hash_count; ++i) { |
| 857 | hashes[i] = ((&APR_ARRAY_IDX(diary->entries, i, h2_push_diary_entry))->hash |
| 858 | >> encoder.delta_bits); |
| 859 | } |
| 860 | |
| 861 | qsort(hashes, hash_count, sizeof(apr_uint64_t), cmp_puint64); |
| 862 | for (i = 0; i < hash_count; ++i) { |
| 863 | if (!i || (hashes[i] != hashes[i-1])) { |
nothing calls this directly
no test coverage detected