OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/proxy/proxy_list.h" | 5 #include "net/proxy/proxy_list.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/string_tokenizer.h" | 9 #include "base/string_tokenizer.h" |
10 #include "base/time.h" | 10 #include "base/time.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 } | 60 } |
61 } | 61 } |
62 good_proxies.push_back(*iter); | 62 good_proxies.push_back(*iter); |
63 } | 63 } |
64 | 64 |
65 // "proxies_ = good_proxies + bad_proxies" | 65 // "proxies_ = good_proxies + bad_proxies" |
66 proxies_.swap(good_proxies); | 66 proxies_.swap(good_proxies); |
67 proxies_.insert(proxies_.end(), bad_proxies.begin(), bad_proxies.end()); | 67 proxies_.insert(proxies_.end(), bad_proxies.begin(), bad_proxies.end()); |
68 } | 68 } |
69 | 69 |
| 70 bool ProxyList::HasUntriedProxies( |
| 71 const ProxyRetryInfoMap& proxy_retry_info) const { |
| 72 std::vector<ProxyServer>::const_iterator iter = proxies_.begin(); |
| 73 for (; iter != proxies_.end(); ++iter) { |
| 74 ProxyRetryInfoMap::const_iterator bad_proxy = |
| 75 proxy_retry_info.find(iter->ToURI()); |
| 76 if (bad_proxy != proxy_retry_info.end()) { |
| 77 // This proxy is bad. Check if it's time to retry. |
| 78 if (bad_proxy->second.bad_until >= TimeTicks::Now()) { |
| 79 continue; |
| 80 } |
| 81 } |
| 82 // Either we've found the entry in the retry map and it's expired or we |
| 83 // didn't find a corresponding entry in the retry map. In either case, we |
| 84 // have a proxy to try. |
| 85 return true; |
| 86 } |
| 87 return false; |
| 88 } |
| 89 |
70 void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) { | 90 void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) { |
71 for (std::vector<ProxyServer>::iterator it = proxies_.begin(); | 91 for (std::vector<ProxyServer>::iterator it = proxies_.begin(); |
72 it != proxies_.end(); ) { | 92 it != proxies_.end(); ) { |
73 if (!(scheme_bit_field & it->scheme())) { | 93 if (!(scheme_bit_field & it->scheme())) { |
74 it = proxies_.erase(it); | 94 it = proxies_.erase(it); |
75 continue; | 95 continue; |
76 } | 96 } |
77 ++it; | 97 ++it; |
78 } | 98 } |
79 } | 99 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 for (; iter != proxies_.end(); ++iter) { | 139 for (; iter != proxies_.end(); ++iter) { |
120 if (!proxy_list.empty()) | 140 if (!proxy_list.empty()) |
121 proxy_list += ";"; | 141 proxy_list += ";"; |
122 proxy_list += iter->ToPacString(); | 142 proxy_list += iter->ToPacString(); |
123 } | 143 } |
124 return proxy_list.empty() ? std::string() : proxy_list; | 144 return proxy_list.empty() ? std::string() : proxy_list; |
125 } | 145 } |
126 | 146 |
127 bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info, | 147 bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info, |
128 const BoundNetLog& net_log) { | 148 const BoundNetLog& net_log) { |
129 // Number of minutes to wait before retrying a bad proxy server. | |
130 const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5); | |
131 | 149 |
132 // TODO(eroman): It would be good if instead of removing failed proxies | 150 // TODO(eroman): It would be good if instead of removing failed proxies |
133 // from the list, we simply annotated them with the error code they failed | 151 // from the list, we simply annotated them with the error code they failed |
134 // with. Of course, ProxyService::ReconsiderProxyAfterError() would need to | 152 // with. Of course, ProxyService::ReconsiderProxyAfterError() would need to |
135 // be given this information by the network transaction. | 153 // be given this information by the network transaction. |
136 // | 154 // |
137 // The advantage of this approach is when the network transaction | 155 // The advantage of this approach is when the network transaction |
138 // fails, we could output the full list of proxies that were attempted, and | 156 // fails, we could output the full list of proxies that were attempted, and |
139 // why each one of those failed (as opposed to just the last failure). | 157 // why each one of those failed (as opposed to just the last failure). |
140 // | 158 // |
141 // And also, before failing the transaction wholesale, we could go back and | 159 // And also, before failing the transaction wholesale, we could go back and |
142 // retry the "bad proxies" which we never tried to begin with. | 160 // retry the "bad proxies" which we never tried to begin with. |
143 // (RemoveBadProxies would annotate them as 'expected bad' rather then delete | 161 // (RemoveBadProxies would annotate them as 'expected bad' rather then delete |
144 // them from the list, so we would know what they were). | 162 // them from the list, so we would know what they were). |
145 | 163 |
146 if (proxies_.empty()) { | 164 if (proxies_.empty()) { |
147 NOTREACHED(); | 165 NOTREACHED(); |
148 return false; | 166 return false; |
149 } | 167 } |
| 168 UpdateRetryInfoOnFallback(proxy_retry_info, net_log); |
| 169 |
| 170 // Remove this proxy from our list. |
| 171 proxies_.erase(proxies_.begin()); |
| 172 return !proxies_.empty(); |
| 173 } |
| 174 |
| 175 void ProxyList::UpdateRetryInfoOnFallback( |
| 176 ProxyRetryInfoMap* proxy_retry_info, const BoundNetLog& net_log) const { |
| 177 // Number of minutes to wait before retrying a bad proxy server. |
| 178 const TimeDelta kProxyRetryDelay = TimeDelta::FromMinutes(5); |
| 179 |
| 180 if (proxies_.empty()) { |
| 181 NOTREACHED(); |
| 182 return; |
| 183 } |
150 | 184 |
151 if (!proxies_[0].is_direct()) { | 185 if (!proxies_[0].is_direct()) { |
152 std::string key = proxies_[0].ToURI(); | 186 std::string key = proxies_[0].ToURI(); |
153 // Mark this proxy as bad. | 187 // Mark this proxy as bad. |
154 ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(key); | 188 ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(key); |
155 if (iter != proxy_retry_info->end()) { | 189 if (iter != proxy_retry_info->end()) { |
156 // TODO(nsylvain): This is not the first time we get this. We should | 190 // TODO(nsylvain): This is not the first time we get this. We should |
157 // double the retry time. Bug 997660. | 191 // double the retry time. Bug 997660. |
158 iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay; | 192 iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay; |
159 } else { | 193 } else { |
160 ProxyRetryInfo retry_info; | 194 ProxyRetryInfo retry_info; |
161 retry_info.current_delay = kProxyRetryDelay; | 195 retry_info.current_delay = kProxyRetryDelay; |
162 retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay; | 196 retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay; |
163 (*proxy_retry_info)[key] = retry_info; | 197 (*proxy_retry_info)[key] = retry_info; |
164 } | 198 } |
165 net_log.AddEvent(NetLog::TYPE_PROXY_LIST_FALLBACK, | 199 net_log.AddEvent(NetLog::TYPE_PROXY_LIST_FALLBACK, |
166 NetLog::StringCallback("bad_proxy", &key)); | 200 NetLog::StringCallback("bad_proxy", &key)); |
167 } | 201 } |
168 | |
169 // Remove this proxy from our list. | |
170 proxies_.erase(proxies_.begin()); | |
171 | |
172 return !proxies_.empty(); | |
173 } | 202 } |
174 | 203 |
175 } // namespace net | 204 } // namespace net |
OLD | NEW |