Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: net/url_request/url_request_throttler_manager.cc

Issue 6966038: Anti-DDoS enhancements: Log to net log, UMA stats, improved policy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge to head. Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/url_request/url_request_throttler_manager.h" 5 #include "net/url_request/url_request_throttler_manager.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/metrics/field_trial.h"
9 #include "base/metrics/histogram.h"
8 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "net/base/net_log.h"
9 #include "net/base/net_util.h" 12 #include "net/base/net_util.h"
10 13
11 namespace net { 14 namespace net {
12 15
13 const unsigned int URLRequestThrottlerManager::kMaximumNumberOfEntries = 1500; 16 const unsigned int URLRequestThrottlerManager::kMaximumNumberOfEntries = 1500;
14 const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200; 17 const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200;
15 18
16 URLRequestThrottlerManager* URLRequestThrottlerManager::GetInstance() { 19 URLRequestThrottlerManager* URLRequestThrottlerManager::GetInstance() {
17 return Singleton<URLRequestThrottlerManager>::get(); 20 return Singleton<URLRequestThrottlerManager>::get();
18 } 21 }
19 22
20 scoped_refptr<URLRequestThrottlerEntryInterface> 23 scoped_refptr<URLRequestThrottlerEntryInterface>
21 URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) { 24 URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) {
22 DCHECK(!enable_thread_checks_ || CalledOnValidThread()); 25 DCHECK(!enable_thread_checks_ || CalledOnValidThread());
23 26
24 // Normalize the url. 27 // Normalize the url.
25 std::string url_id = GetIdFromUrl(url); 28 std::string url_id = GetIdFromUrl(url);
26 29
27 // Periodically garbage collect old entries. 30 // Periodically garbage collect old entries.
28 GarbageCollectEntriesIfNecessary(); 31 GarbageCollectEntriesIfNecessary();
29 32
30 // Find the entry in the map or create it. 33 // Find the entry in the map or create a new NULL entry.
31 scoped_refptr<URLRequestThrottlerEntry>& entry = url_entries_[url_id]; 34 scoped_refptr<URLRequestThrottlerEntry>& entry = url_entries_[url_id];
35
36 // If the entry exists but could be garbage collected at this point, we
37 // start with a fresh entry so that we possibly back off a bit less
38 // aggressively (i.e. this resets the error count when the entry's URL
39 // hasn't been requested in long enough).
40 if (entry.get() && entry->IsEntryOutdated()) {
41 entry = NULL;
42 }
43
44 // Create the entry if needed.
32 if (entry.get() == NULL) { 45 if (entry.get() == NULL) {
33 entry = new URLRequestThrottlerEntry(this); 46 entry = new URLRequestThrottlerEntry(this, url_id);
34 47
35 // We only disable back-off throttling on an entry that we have 48 // We only disable back-off throttling on an entry that we have
36 // just constructed. This is to allow unit tests to explicitly override 49 // just constructed. This is to allow unit tests to explicitly override
37 // the entry for localhost URLs. Given that we do not attempt to 50 // the entry for localhost URLs. Given that we do not attempt to
38 // disable throttling for entries already handed out (see comment 51 // disable throttling for entries already handed out (see comment
39 // in AddToOptOutList), this is not a problem. 52 // in AddToOptOutList), this is not a problem.
40 std::string host = url.host(); 53 std::string host = url.host();
41 if (opt_out_hosts_.find(host) != opt_out_hosts_.end() || 54 if (opt_out_hosts_.find(host) != opt_out_hosts_.end() ||
42 IsLocalhost(host)) { 55 IsLocalhost(host)) {
56 if (!logged_for_localhost_disabled_ && IsLocalhost(host)) {
57 logged_for_localhost_disabled_ = true;
58 net_log_->AddEvent(
59 NetLog::TYPE_THROTTLING_DISABLED_FOR_HOST,
60 make_scoped_refptr(new NetLogStringParameter("host", host)));
61 }
62
43 // TODO(joi): Once sliding window is separate from back-off throttling, 63 // TODO(joi): Once sliding window is separate from back-off throttling,
44 // we can simply return a dummy implementation of 64 // we can simply return a dummy implementation of
45 // URLRequestThrottlerEntryInterface here that never blocks anything (and 65 // URLRequestThrottlerEntryInterface here that never blocks anything (and
46 // not keep entries in url_entries_ for opted-out sites). 66 // not keep entries in url_entries_ for opted-out sites).
47 entry->DisableBackoffThrottling(); 67 entry->DisableBackoffThrottling();
48 } 68 }
49 } 69 }
50 70
51 return entry; 71 return entry;
52 } 72 }
53 73
54 void URLRequestThrottlerManager::AddToOptOutList(const std::string& host) { 74 void URLRequestThrottlerManager::AddToOptOutList(const std::string& host) {
55 // There is an edge case here that we are not handling, to keep things 75 // There is an edge case here that we are not handling, to keep things
56 // simple. If a host starts adding the opt-out header to its responses 76 // simple. If a host starts adding the opt-out header to its responses
57 // after there are already one or more entries in url_entries_ for that 77 // after there are already one or more entries in url_entries_ for that
58 // host, the pre-existing entries may still perform back-off throttling. 78 // host, the pre-existing entries may still perform back-off throttling.
59 // In practice, this would almost never occur. 79 // In practice, this would almost never occur.
60 opt_out_hosts_.insert(host); 80 if (opt_out_hosts_.find(host) == opt_out_hosts_.end()) {
81 UMA_HISTOGRAM_COUNTS("Throttling.SiteOptedOut", 1);
82 if (base::FieldTrialList::TrialExists("ThrottlingEnabled")) {
83 UMA_HISTOGRAM_COUNTS(base::FieldTrial::MakeName(
84 "Throttling.SiteOptedOut", "ThrottlingEnabled"), 1);
85 }
86
87 net_log_->EndEvent(
88 NetLog::TYPE_THROTTLING_DISABLED_FOR_HOST,
89 make_scoped_refptr(new NetLogStringParameter("host", host)));
90 opt_out_hosts_.insert(host);
91 }
61 } 92 }
62 93
63 void URLRequestThrottlerManager::OverrideEntryForTests( 94 void URLRequestThrottlerManager::OverrideEntryForTests(
64 const GURL& url, 95 const GURL& url,
65 URLRequestThrottlerEntry* entry) { 96 URLRequestThrottlerEntry* entry) {
66 // Normalize the url. 97 // Normalize the url.
67 std::string url_id = GetIdFromUrl(url); 98 std::string url_id = GetIdFromUrl(url);
68 99
69 // Periodically garbage collect old entries. 100 // Periodically garbage collect old entries.
70 GarbageCollectEntriesIfNecessary(); 101 GarbageCollectEntriesIfNecessary();
(...skipping 16 matching lines...) Expand all
87 } 118 }
88 119
89 void URLRequestThrottlerManager::set_enforce_throttling(bool enforce) { 120 void URLRequestThrottlerManager::set_enforce_throttling(bool enforce) {
90 enforce_throttling_ = enforce; 121 enforce_throttling_ = enforce;
91 } 122 }
92 123
93 bool URLRequestThrottlerManager::enforce_throttling() { 124 bool URLRequestThrottlerManager::enforce_throttling() {
94 return enforce_throttling_; 125 return enforce_throttling_;
95 } 126 }
96 127
128 void URLRequestThrottlerManager::set_net_log(NetLog* net_log) {
129 DCHECK(net_log);
130 NetLog::Source source(NetLog::SOURCE_EXPONENTIAL_BACKOFF_THROTTLING,
131 net_log->NextID());
132 net_log_.reset(new BoundNetLog(source, net_log));
133 }
134
135 NetLog* URLRequestThrottlerManager::net_log() const {
136 return net_log_->net_log();
137 }
138
139 void URLRequestThrottlerManager::OnIPAddressChanged() {
140 OnNetworkChange();
141 }
142
143 void URLRequestThrottlerManager::OnOnlineStateChanged(bool online) {
144 OnNetworkChange();
145 }
146
97 // TODO(joi): Turn throttling on by default when appropriate. 147 // TODO(joi): Turn throttling on by default when appropriate.
98 URLRequestThrottlerManager::URLRequestThrottlerManager() 148 URLRequestThrottlerManager::URLRequestThrottlerManager()
99 : requests_since_last_gc_(0), 149 : requests_since_last_gc_(0),
100 enforce_throttling_(false), 150 enforce_throttling_(false),
101 enable_thread_checks_(false) { 151 enable_thread_checks_(false),
152 logged_for_localhost_disabled_(false) {
102 // Construction/destruction is on main thread (because BrowserMain 153 // Construction/destruction is on main thread (because BrowserMain
103 // retrieves an instance to call InitializeOptions), but is from then on 154 // retrieves an instance to call InitializeOptions), but is from then on
104 // used on I/O thread. 155 // used on I/O thread.
105 DetachFromThread(); 156 DetachFromThread();
106 157
107 url_id_replacements_.ClearPassword(); 158 url_id_replacements_.ClearPassword();
108 url_id_replacements_.ClearUsername(); 159 url_id_replacements_.ClearUsername();
109 url_id_replacements_.ClearQuery(); 160 url_id_replacements_.ClearQuery();
110 url_id_replacements_.ClearRef(); 161 url_id_replacements_.ClearRef();
162
163 // Make sure there is always a net_log_ instance, even if it logs to
164 // nowhere.
165 net_log_.reset(new BoundNetLog());
166
167 NetworkChangeNotifier::AddIPAddressObserver(this);
168 NetworkChangeNotifier::AddOnlineStateObserver(this);
111 } 169 }
112 170
113 URLRequestThrottlerManager::~URLRequestThrottlerManager() { 171 URLRequestThrottlerManager::~URLRequestThrottlerManager() {
114 // Destruction is on main thread (AtExit), but real use is on I/O thread. 172 // Destruction is on main thread (AtExit), but real use is on I/O thread.
115 DetachFromThread(); 173 DetachFromThread();
116 174
175 NetworkChangeNotifier::RemoveIPAddressObserver(this);
176 NetworkChangeNotifier::RemoveOnlineStateObserver(this);
177
117 // Since, for now, the manager object might conceivably go away before 178 // Since, for now, the manager object might conceivably go away before
118 // the entries, detach the entries' back-pointer to the manager. 179 // the entries, detach the entries' back-pointer to the manager.
119 // 180 //
120 // TODO(joi): Revisit whether to make entries non-refcounted. 181 // TODO(joi): Revisit whether to make entries non-refcounted.
121 UrlEntryMap::iterator i = url_entries_.begin(); 182 UrlEntryMap::iterator i = url_entries_.begin();
122 while (i != url_entries_.end()) { 183 while (i != url_entries_.end()) {
123 if (i->second != NULL) { 184 if (i->second != NULL) {
124 i->second->DetachManager(); 185 i->second->DetachManager();
125 } 186 }
126 ++i; 187 ++i;
(...skipping 29 matching lines...) Expand all
156 ++i; 217 ++i;
157 } 218 }
158 } 219 }
159 220
160 // In case something broke we want to make sure not to grow indefinitely. 221 // In case something broke we want to make sure not to grow indefinitely.
161 while (url_entries_.size() > kMaximumNumberOfEntries) { 222 while (url_entries_.size() > kMaximumNumberOfEntries) {
162 url_entries_.erase(url_entries_.begin()); 223 url_entries_.erase(url_entries_.begin());
163 } 224 }
164 } 225 }
165 226
227 void URLRequestThrottlerManager::OnNetworkChange() {
228 // Remove all entries. Any entries that in-flight requests have a reference
229 // to will live until those requests end, and these entries may be
230 // inconsistent with new entries for the same URLs, but since what we
231 // want is a clean slate for the new connection state, this is OK.
232 url_entries_.clear();
233 requests_since_last_gc_ = 0;
234 }
235
166 } // namespace net 236 } // namespace net
OLDNEW
« no previous file with comments | « net/url_request/url_request_throttler_manager.h ('k') | net/url_request/url_request_throttler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698