// 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 "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) { *final_error = error; if (!proxy_chain.is_direct() && proxy_chain.GetProxyServer(/*chain_index=*/0).is_quic()) { // TODO(https://crbug.com/1495793): For supporting QUIC with proxy chains // containing more than one proxy server it's unclear whether the proxy // server at chain index 0 is really what we should be doing here. Figure // that out and add tests. CHECK(!proxy_chain.is_multi_proxy()); 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