| // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/spdy/spdy_header_indexing.h" |
| |
| #include "net/spdy/spdy_bug_tracker.h" |
| |
| using base::StringPiece; |
| |
| namespace net { |
| |
| int32_t FLAGS_gfe_spdy_indexing_set_bound = 300; |
| int32_t FLAGS_gfe_spdy_tracking_set_bound = 2000; |
| |
| HeaderIndexing::HeaderIndexing() |
| : indexing_set_bound_(FLAGS_gfe_spdy_indexing_set_bound), |
| tracking_set_bound_(FLAGS_gfe_spdy_tracking_set_bound) { |
| SPDY_BUG_IF(indexing_set_bound_ >= tracking_set_bound_) |
| << "Tracking set should be larger than indexing set"; |
| } |
| |
| HeaderIndexing::~HeaderIndexing() {} |
| |
| void HeaderIndexing::CreateInitIndexingHeaders() { |
| const std::string initial_fields[] = { |
| // Estimated top 100 fields. |
| "alt-svc", |
| "date", |
| "cache-control", |
| "content-type", |
| "expires", |
| "location", |
| "x-xss-protection", |
| "p3p", |
| "set-cookie", |
| "alternate-protocol", |
| "last-modified", |
| "server", |
| "x-snapchat-request-id", |
| "content-disposition", |
| "strict-transport-security", |
| "x-content-type-options", |
| "content-security-policy", |
| "x-frame-options", |
| "x-snapchat-notice", |
| "pragma", |
| ":status", |
| "content-length", |
| "etag", |
| "x-cloud-trace-context", |
| "vary", |
| "access-control-expose-headers", |
| "content-encoding", |
| "access-control-allow-origin", |
| "age", |
| ":protocol", |
| "via", |
| "x-robots-tag", |
| "link", |
| "access-control-allow-headers", |
| "x-google-session-info", |
| "x-google-backends", |
| "x-google-gfe-request-trace", |
| "warning", |
| "x-guploader-uploadid", |
| "x-cup-server-proof", |
| "timing-allow-origin", |
| "x-google-trace", |
| "access-control-allow-credentials", |
| "google-delayed-impression", |
| "google-creative-id", |
| "access-control-allow-methods", |
| "x-ua-compatible", |
| "x-google-gfe-response-code-details-trace", |
| "google-lineitem-id", |
| "version", |
| "x-google-dos-service-trace", |
| "x-google-service", |
| "x-google-gfe-service-trace", |
| "sane-time-millis", |
| "x-google-netmon-label", |
| "x-google-apiary-auth-scopes", |
| "x-seed-signature", |
| "content-security-policy-report-only", |
| "x-auto-login", |
| "x-original-content-length", |
| "accept-ranges", |
| "x-goog-hash", |
| "x-google-gfe-response-body-transformations", |
| "cf-ray", |
| "x-content-security-policy-report-only", |
| "x-google-shellfish-status", |
| "x-amz-id-2", |
| "get-dictionary", |
| "grpc-message", |
| "x-hw", |
| "x-google-gfe-backend-request-info", |
| "x-goog-upload-header-x-google-session-info", |
| "x-amz-cf-id", |
| "x-powered-by", |
| "www-authenticate", |
| "access-control-max-age", |
| "x-spf-response-type", |
| "x-goog-meta-encoded_request", |
| "x-goog-generation", |
| "x-google-gslb-service", |
| "x-google-servertype", |
| "x-cache", |
| "x-chromium-appcache-fallback-override", |
| "x-goog-upload-url", |
| "x-goog-upload-control-url", |
| "content-range", |
| "x-seen-by", |
| "x-google-apps-framework-action", |
| "content-location", |
| "x-daystart", |
| "x-varnish", |
| "fastly-debug-digest", |
| "x-daynum", |
| "x-goog-stored-content-encoding", |
| "x-goog-storage-class", |
| "x-google-cookies-blocked", |
| "x-range-md5", |
| "x-served-by", |
| "x-client-wire-protocol", |
| "content-language", |
| }; |
| |
| indexing_set_.clear(); |
| indexing_set_ = |
| HeaderSet(initial_fields, initial_fields + arraysize(initial_fields)); |
| tracking_set_ = |
| HeaderSet(initial_fields, initial_fields + arraysize(initial_fields)); |
| } |
| |
| bool HeaderIndexing::ShouldIndex(StringPiece header, StringPiece /* value */) { |
| if (header.empty()) { |
| return false; |
| } |
| // header is in indexing set. |
| std::string header_str(header.data(), header.size()); |
| if (indexing_set_.find(header_str) != indexing_set_.end()) { |
| return true; |
| } |
| // header not in indexing set. Check tracking set. |
| if (tracking_set_.find(header_str) != tracking_set_.end()) { |
| // Seen this header before. Add it to indexing set. |
| TryInsertHeader(std::move(header_str), &indexing_set_, indexing_set_bound_); |
| } else { |
| // Add header to tracking set. |
| TryInsertHeader(std::move(header_str), &tracking_set_, tracking_set_bound_); |
| } |
| return false; |
| } |
| |
| void HeaderIndexing::TryInsertHeader(std::string&& header, |
| HeaderSet* set, |
| size_t bound) { |
| std::pair<HeaderSet::iterator, bool> result = set->insert(std::move(header)); |
| if (set->size() > bound) { |
| // Reach the size limit. Remove the header next to the newly added header. |
| // If the new header is at the end, look for the "next" element at the |
| // beginning. |
| HeaderSet::iterator it = std::next(result.first); |
| if (it != set->end()) { |
| set->erase(it); |
| } else { |
| set->erase(set->begin()); |
| } |
| } |
| } |
| |
| } // namespace net |