File: proxy_fallback.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (103 lines) | stat: -rw-r--r-- 4,112 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/proxy_fallback.h"

#include "base/metrics/histogram_functions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/net_errors.h"
#include "net/base/proxy_chain.h"
#include "net/base/proxy_server.h"

namespace net {

NET_EXPORT bool CanFalloverToNextProxy(const ProxyChain& proxy_chain,
                                       int error,
                                       int* final_error,
                                       bool is_for_ip_protection) {
  if (is_for_ip_protection) {
    // Log the error.
    // Useful to know if errors not handled below are passed to this function.
    if (const int chain_id = proxy_chain.ip_protection_chain_id();
        chain_id != ProxyChain::kNotIpProtectionChainId) {
      base::UmaHistogramSparse(
          base::StrCat({"Net.IpProtection.CanFalloverToNextProxy.Error.Chain",
                        base::NumberToString(chain_id)}),
          error);
    }
  }
  *final_error = error;
  const auto& proxy_servers = proxy_chain.proxy_servers();
  const bool has_quic_proxy = std::any_of(
      proxy_servers.begin(), proxy_servers.end(),
      [](const ProxyServer& proxy_server) { return proxy_server.is_quic(); });
  if (!proxy_chain.is_direct() && has_quic_proxy) {
    // The whole chain should be QUIC.
    for (const auto& proxy_server : proxy_servers) {
      CHECK(proxy_server.is_quic());
    }
    switch (error) {
      case ERR_QUIC_PROTOCOL_ERROR:
      case ERR_QUIC_HANDSHAKE_FAILED:
      case ERR_MSG_TOO_BIG:
        return true;
    }
  }

  // TODO(eroman): Split up these error codes across the relevant proxy types.
  //
  // A failure to resolve the hostname or any error related to establishing a
  // TCP connection could be grounds for trying a new proxy configuration.
  //
  // Why do this when a hostname cannot be resolved?  Some URLs only make sense
  // to proxy servers.  The hostname in those URLs might fail to resolve if we
  // are still using a non-proxy config.  We need to check if a proxy config
  // now exists that corresponds to a proxy server that could load the URL.

  switch (error) {
    case ERR_PROXY_CONNECTION_FAILED:
    case ERR_NAME_NOT_RESOLVED:
    case ERR_INTERNET_DISCONNECTED:
    case ERR_ADDRESS_UNREACHABLE:
    case ERR_CONNECTION_CLOSED:
    case ERR_CONNECTION_TIMED_OUT:
    case ERR_CONNECTION_RESET:
    case ERR_CONNECTION_REFUSED:
    case ERR_CONNECTION_ABORTED:
    case ERR_TIMED_OUT:
    case ERR_SOCKS_CONNECTION_FAILED:
    // ERR_PROXY_CERTIFICATE_INVALID can happen in the case of trying to talk to
    // a proxy using SSL, and ending up talking to a captive portal that
    // supports SSL instead.
    case ERR_PROXY_CERTIFICATE_INVALID:
    // ERR_SSL_PROTOCOL_ERROR can happen when trying to talk SSL to a non-SSL
    // server (like a captive portal).
    case ERR_SSL_PROTOCOL_ERROR:
      return true;

    case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
      // Remap the SOCKS-specific "host unreachable" error to a more
      // generic error code (this way consumers like the link doctor
      // know to substitute their error page).
      //
      // Note that if the host resolving was done by the SOCKS5 proxy, we can't
      // differentiate between a proxy-side "host not found" versus a proxy-side
      // "address unreachable" error, and will report both of these failures as
      // ERR_ADDRESS_UNREACHABLE.
      *final_error = ERR_ADDRESS_UNREACHABLE;
      return false;

    case ERR_TUNNEL_CONNECTION_FAILED:
      // A failure while establishing a tunnel to the proxy is only considered
      // grounds for fallback when connecting to an IP Protection proxy. Other
      // browsers similarly don't fallback, and some client's PAC configurations
      // rely on this for some degree of content blocking. See
      // https://crbug.com/680837 for details.
      return is_for_ip_protection;
  }
  return false;
}

}  // namespace net