proxy_list.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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
  3. // found in the LICENSE file.
  4. #include "net/proxy_resolution/proxy_list.h"
  5. #include "base/callback.h"
  6. #include "base/check.h"
  7. #include "base/notreached.h"
  8. #include "base/strings/string_tokenizer.h"
  9. #include "base/time/time.h"
  10. #include "base/values.h"
  11. #include "net/base/proxy_server.h"
  12. #include "net/base/proxy_string_util.h"
  13. #include "net/log/net_log.h"
  14. #include "net/log/net_log_event_type.h"
  15. #include "net/log/net_log_with_source.h"
  16. using base::TimeTicks;
  17. namespace net {
  18. ProxyList::ProxyList() = default;
  19. ProxyList::ProxyList(const ProxyList& other) = default;
  20. ProxyList::ProxyList(ProxyList&& other) = default;
  21. ProxyList& ProxyList::operator=(const ProxyList& other) = default;
  22. ProxyList& ProxyList::operator=(ProxyList&& other) = default;
  23. ProxyList::~ProxyList() = default;
  24. void ProxyList::Set(const std::string& proxy_uri_list) {
  25. proxies_.clear();
  26. base::StringTokenizer str_tok(proxy_uri_list, ";");
  27. while (str_tok.GetNext()) {
  28. ProxyServer uri =
  29. ProxyUriToProxyServer(str_tok.token_piece(), ProxyServer::SCHEME_HTTP);
  30. // Silently discard malformed inputs.
  31. if (uri.is_valid())
  32. proxies_.push_back(uri);
  33. }
  34. }
  35. void ProxyList::SetSingleProxyServer(const ProxyServer& proxy_server) {
  36. proxies_.clear();
  37. AddProxyServer(proxy_server);
  38. }
  39. void ProxyList::AddProxyServer(const ProxyServer& proxy_server) {
  40. if (proxy_server.is_valid())
  41. proxies_.push_back(proxy_server);
  42. }
  43. void ProxyList::DeprioritizeBadProxies(
  44. const ProxyRetryInfoMap& proxy_retry_info) {
  45. // Partition the proxy list in two:
  46. // (1) the known bad proxies
  47. // (2) everything else
  48. std::vector<ProxyServer> good_proxies;
  49. std::vector<ProxyServer> bad_proxies_to_try;
  50. std::vector<ProxyServer>::const_iterator iter = proxies_.begin();
  51. for (; iter != proxies_.end(); ++iter) {
  52. auto bad_proxy = proxy_retry_info.find(ProxyServerToProxyUri(*iter));
  53. if (bad_proxy != proxy_retry_info.end()) {
  54. // This proxy is bad. Check if it's time to retry.
  55. if (bad_proxy->second.bad_until >= TimeTicks::Now()) {
  56. // still invalid.
  57. if (bad_proxy->second.try_while_bad)
  58. bad_proxies_to_try.push_back(*iter);
  59. continue;
  60. }
  61. }
  62. good_proxies.push_back(*iter);
  63. }
  64. // "proxies_ = good_proxies + bad_proxies"
  65. proxies_.swap(good_proxies);
  66. proxies_.insert(proxies_.end(), bad_proxies_to_try.begin(),
  67. bad_proxies_to_try.end());
  68. }
  69. void ProxyList::RemoveProxiesWithoutScheme(int scheme_bit_field) {
  70. for (auto it = proxies_.begin(); it != proxies_.end();) {
  71. if (!(scheme_bit_field & it->scheme())) {
  72. it = proxies_.erase(it);
  73. continue;
  74. }
  75. ++it;
  76. }
  77. }
  78. void ProxyList::Clear() {
  79. proxies_.clear();
  80. }
  81. bool ProxyList::IsEmpty() const {
  82. return proxies_.empty();
  83. }
  84. size_t ProxyList::size() const {
  85. return proxies_.size();
  86. }
  87. // Returns true if |*this| lists the same proxies as |other|.
  88. bool ProxyList::Equals(const ProxyList& other) const {
  89. if (size() != other.size())
  90. return false;
  91. return proxies_ == other.proxies_;
  92. }
  93. const ProxyServer& ProxyList::Get() const {
  94. CHECK(!proxies_.empty());
  95. return proxies_[0];
  96. }
  97. const std::vector<ProxyServer>& ProxyList::GetAll() const {
  98. return proxies_;
  99. }
  100. void ProxyList::SetFromPacString(const std::string& pac_string) {
  101. base::StringTokenizer entry_tok(pac_string, ";");
  102. proxies_.clear();
  103. while (entry_tok.GetNext()) {
  104. ProxyServer uri = PacResultElementToProxyServer(entry_tok.token_piece());
  105. // Silently discard malformed inputs.
  106. if (uri.is_valid())
  107. proxies_.push_back(uri);
  108. }
  109. // If we failed to parse anything from the PAC results list, fallback to
  110. // DIRECT (this basically means an error in the PAC script).
  111. if (proxies_.empty()) {
  112. proxies_.push_back(ProxyServer::Direct());
  113. }
  114. }
  115. std::string ProxyList::ToPacString() const {
  116. std::string proxy_list;
  117. auto iter = proxies_.begin();
  118. for (; iter != proxies_.end(); ++iter) {
  119. if (!proxy_list.empty())
  120. proxy_list += ";";
  121. proxy_list += ProxyServerToPacResultElement(*iter);
  122. }
  123. return proxy_list.empty() ? std::string() : proxy_list;
  124. }
  125. base::Value ProxyList::ToValue() const {
  126. base::Value list(base::Value::Type::LIST);
  127. for (const auto& proxy : proxies_)
  128. list.Append(ProxyServerToProxyUri(proxy));
  129. return list;
  130. }
  131. bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info,
  132. int net_error,
  133. const NetLogWithSource& net_log) {
  134. if (proxies_.empty()) {
  135. NOTREACHED();
  136. return false;
  137. }
  138. // By default, proxies are not retried for 5 minutes.
  139. UpdateRetryInfoOnFallback(proxy_retry_info, base::Minutes(5), true,
  140. std::vector<ProxyServer>(), net_error, net_log);
  141. // Remove this proxy from our list.
  142. proxies_.erase(proxies_.begin());
  143. return !proxies_.empty();
  144. }
  145. void ProxyList::AddProxyToRetryList(ProxyRetryInfoMap* proxy_retry_info,
  146. base::TimeDelta retry_delay,
  147. bool try_while_bad,
  148. const ProxyServer& proxy_to_retry,
  149. int net_error,
  150. const NetLogWithSource& net_log) const {
  151. // Mark this proxy as bad.
  152. TimeTicks bad_until = TimeTicks::Now() + retry_delay;
  153. std::string proxy_key = ProxyServerToProxyUri(proxy_to_retry);
  154. auto iter = proxy_retry_info->find(proxy_key);
  155. if (iter == proxy_retry_info->end() || bad_until > iter->second.bad_until) {
  156. ProxyRetryInfo retry_info;
  157. retry_info.current_delay = retry_delay;
  158. retry_info.bad_until = bad_until;
  159. retry_info.try_while_bad = try_while_bad;
  160. retry_info.net_error = net_error;
  161. (*proxy_retry_info)[proxy_key] = retry_info;
  162. }
  163. net_log.AddEventWithStringParams(NetLogEventType::PROXY_LIST_FALLBACK,
  164. "bad_proxy", proxy_key);
  165. }
  166. void ProxyList::UpdateRetryInfoOnFallback(
  167. ProxyRetryInfoMap* proxy_retry_info,
  168. base::TimeDelta retry_delay,
  169. bool reconsider,
  170. const std::vector<ProxyServer>& additional_proxies_to_bypass,
  171. int net_error,
  172. const NetLogWithSource& net_log) const {
  173. DCHECK(!retry_delay.is_zero());
  174. if (proxies_.empty()) {
  175. NOTREACHED();
  176. return;
  177. }
  178. if (!proxies_[0].is_direct()) {
  179. AddProxyToRetryList(proxy_retry_info,
  180. retry_delay,
  181. reconsider,
  182. proxies_[0],
  183. net_error,
  184. net_log);
  185. // If any additional proxies to bypass are specified, add to the retry map
  186. // as well.
  187. for (const ProxyServer& additional_proxy : additional_proxies_to_bypass) {
  188. AddProxyToRetryList(proxy_retry_info, retry_delay, reconsider,
  189. additional_proxy, net_error, net_log);
  190. }
  191. }
  192. }
  193. } // namespace net