xref: /aosp_15_r20/external/cronet/net/http/proxy_fallback.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/http/proxy_fallback.h"
6 
7 #include "net/base/net_errors.h"
8 #include "net/base/proxy_chain.h"
9 #include "net/base/proxy_server.h"
10 
11 namespace net {
12 
CanFalloverToNextProxy(const ProxyChain & proxy_chain,int error,int * final_error,bool is_for_ip_protection)13 NET_EXPORT bool CanFalloverToNextProxy(const ProxyChain& proxy_chain,
14                                        int error,
15                                        int* final_error,
16                                        bool is_for_ip_protection) {
17   *final_error = error;
18   auto proxy_servers = proxy_chain.proxy_servers();
19   bool has_quic_proxy = std::any_of(
20       proxy_servers.begin(), proxy_servers.end(),
21       [](const ProxyServer& proxy_server) { return proxy_server.is_quic(); });
22   if (!proxy_chain.is_direct() && has_quic_proxy) {
23     // The whole chain should be QUIC.
24     for (const auto& proxy_server : proxy_servers) {
25       CHECK(proxy_server.is_quic());
26     }
27     switch (error) {
28       case ERR_QUIC_PROTOCOL_ERROR:
29       case ERR_QUIC_HANDSHAKE_FAILED:
30       case ERR_MSG_TOO_BIG:
31         return true;
32     }
33   }
34 
35   // TODO(eroman): Split up these error codes across the relevant proxy types.
36   //
37   // A failure to resolve the hostname or any error related to establishing a
38   // TCP connection could be grounds for trying a new proxy configuration.
39   //
40   // Why do this when a hostname cannot be resolved?  Some URLs only make sense
41   // to proxy servers.  The hostname in those URLs might fail to resolve if we
42   // are still using a non-proxy config.  We need to check if a proxy config
43   // now exists that corresponds to a proxy server that could load the URL.
44 
45   switch (error) {
46     case ERR_PROXY_CONNECTION_FAILED:
47     case ERR_NAME_NOT_RESOLVED:
48     case ERR_INTERNET_DISCONNECTED:
49     case ERR_ADDRESS_UNREACHABLE:
50     case ERR_CONNECTION_CLOSED:
51     case ERR_CONNECTION_TIMED_OUT:
52     case ERR_CONNECTION_RESET:
53     case ERR_CONNECTION_REFUSED:
54     case ERR_CONNECTION_ABORTED:
55     case ERR_TIMED_OUT:
56     case ERR_SOCKS_CONNECTION_FAILED:
57     // ERR_PROXY_CERTIFICATE_INVALID can happen in the case of trying to talk to
58     // a proxy using SSL, and ending up talking to a captive portal that
59     // supports SSL instead.
60     case ERR_PROXY_CERTIFICATE_INVALID:
61     // ERR_SSL_PROTOCOL_ERROR can happen when trying to talk SSL to a non-SSL
62     // server (like a captive portal).
63     case ERR_SSL_PROTOCOL_ERROR:
64       return true;
65 
66     case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
67       // Remap the SOCKS-specific "host unreachable" error to a more
68       // generic error code (this way consumers like the link doctor
69       // know to substitute their error page).
70       //
71       // Note that if the host resolving was done by the SOCKS5 proxy, we can't
72       // differentiate between a proxy-side "host not found" versus a proxy-side
73       // "address unreachable" error, and will report both of these failures as
74       // ERR_ADDRESS_UNREACHABLE.
75       *final_error = ERR_ADDRESS_UNREACHABLE;
76       return false;
77 
78     case ERR_TUNNEL_CONNECTION_FAILED:
79       // A failure while establishing a tunnel to the proxy is only considered
80       // grounds for fallback when connecting to an IP Protection proxy. Other
81       // browsers similarly don't fallback, and some client's PAC configurations
82       // rely on this for some degree of content blocking. See
83       // https://crbug.com/680837 for details.
84       return is_for_ip_protection;
85   }
86   return false;
87 }
88 
89 }  // namespace net
90