1 // Copyright 2023 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 #ifndef NET_BASE_PROXY_CHAIN_H_ 6 #define NET_BASE_PROXY_CHAIN_H_ 7 8 #include <stdint.h> 9 10 #include <optional> 11 #include <ostream> 12 #include <string> 13 #include <string_view> 14 #include <tuple> 15 #include <vector> 16 17 #include "net/base/host_port_pair.h" 18 #include "net/base/net_export.h" 19 #include "net/base/proxy_server.h" 20 21 namespace net { 22 23 // ProxyChain represents a chain of ProxyServers. A chain with multiple proxy 24 // servers means that a single connection will go through all of the proxies in 25 // order, using a tunnel through the first proxy to connect to the second, etc. 26 // A "direct" connection is a chain of length zero. 27 // 28 // TODO(crbug.com/1491092): Initial implementations of proxy chaining may, in 29 // fact, not tunnel through the last proxy in the ProxyChain if the destination 30 // is http. 31 class NET_EXPORT ProxyChain { 32 public: 33 // Constructs an invalid ProxyChain. 34 ProxyChain(); 35 36 ProxyChain(const ProxyChain& other); // Copy constructor 37 ProxyChain(ProxyChain&& other) noexcept; // Move constructor 38 39 ProxyChain& operator=(const ProxyChain& other); // Copy assignment operator 40 ProxyChain& operator=( 41 ProxyChain&& other) noexcept; // Move assignment operator 42 43 ProxyChain(ProxyServer::Scheme scheme, const HostPortPair& host_port_pair); 44 45 explicit ProxyChain(std::vector<ProxyServer> proxy_server_list); 46 explicit ProxyChain(ProxyServer proxy_server); 47 48 ~ProxyChain(); // Destructor declaration 49 50 // Creates a single-proxy ProxyChain, validating and canonicalizing input. 51 // Port is optional and, if not provided, will be replaced with the default 52 // port for the given scheme. Accepts IPv6 literal `host`s with surrounding 53 // brackets (URL format) or without (HostPortPair format). On invalid input, 54 // result will be a `SCHEME_INVALID` ProxyChain. 55 // 56 // Must not be called with `SCHEME_INVALID` or `SCHEME_DIRECT`. Use 57 // `ProxyChain()` or `Direct()` respectively to create an invalid or direct 58 // ProxyChain. FromSchemeHostAndPort(ProxyServer::Scheme scheme,std::string_view host,std::string_view port_str)59 static ProxyChain FromSchemeHostAndPort(ProxyServer::Scheme scheme, 60 std::string_view host, 61 std::string_view port_str) { 62 return ProxyChain( 63 ProxyServer::FromSchemeHostAndPort(scheme, host, port_str)); 64 } FromSchemeHostAndPort(ProxyServer::Scheme scheme,std::string_view host,std::optional<uint16_t> port)65 static ProxyChain FromSchemeHostAndPort(ProxyServer::Scheme scheme, 66 std::string_view host, 67 std::optional<uint16_t> port) { 68 return ProxyChain(ProxyServer::FromSchemeHostAndPort(scheme, host, port)); 69 } 70 // Create a "direct" proxy chain, which includes no proxy servers. Direct()71 static ProxyChain Direct() { return ProxyChain(ProxyServer::Direct()); } 72 73 // Get ProxyServer at index in chain. This is not valid for direct or invalid 74 // proxy chains. 75 const ProxyServer& GetProxyServer(size_t chain_index) const; 76 77 // Get the ProxyServers in this chain. This must not be called on invalid 78 // proxy chains. An empty vector is returned for direct proxy chains. 79 const std::vector<ProxyServer>& proxy_servers() const; 80 81 // Get the ProxyServers in this chain, or `nullopt` if the chain is not valid. proxy_servers_if_valid()82 const std::optional<std::vector<ProxyServer>>& proxy_servers_if_valid() 83 const { 84 return proxy_server_list_; 85 } 86 87 // Get the single ProxyServer equivalent to this chain. This must not be 88 // called for multi-proxy chains. 89 // TODO(crbug.com/1491092): Remove this method. 90 const ProxyServer& proxy_server() const; 91 92 // Returns number of proxy servers in chain. length()93 size_t length() const { 94 return proxy_server_list_.has_value() ? proxy_server_list_.value().size() 95 : 0; 96 } 97 98 // Returns true if this chain contains more than one proxy. is_multi_proxy()99 bool is_multi_proxy() const { 100 return proxy_server_list_.has_value() 101 ? proxy_server_list_.value().size() > 1 102 : false; 103 } 104 105 // Returns true if this chain contains exactly one proxy. is_single_proxy()106 bool is_single_proxy() const { 107 return proxy_server_list_.has_value() 108 ? proxy_server_list_.value().size() == 1 109 : false; 110 } 111 112 // Returns true if this is a direct (equivalently, zero-proxy) chain. is_direct()113 bool is_direct() const { 114 return proxy_server_list_.has_value() ? proxy_server_list_.value().empty() 115 : false; 116 } 117 118 // Returns true if a proxy server list is available . IsValid()119 bool IsValid() const { return proxy_server_list_.has_value(); } 120 121 bool operator==(const ProxyChain& other) const { 122 return proxy_server_list_ == other.proxy_server_list_; 123 } 124 125 bool operator!=(const ProxyChain& other) const { return !(*this == other); } 126 127 // Comparator function so this can be placed in a std::map. 128 bool operator<(const ProxyChain& other) const { 129 return proxy_server_list_ < other.proxy_server_list_; 130 } 131 132 std::string ToDebugString() const; 133 134 private: 135 std::optional<std::vector<ProxyServer>> proxy_server_list_; 136 137 // Returns true if this chain is valid. 138 bool IsValidInternal() const; 139 }; 140 141 NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 142 const ProxyChain& proxy_chain); 143 144 // A HostPortProxyPair holds a host/port destination and a ProxyChain describing 145 // how that destination is reached. 146 typedef std::pair<HostPortPair, ProxyChain> HostPortProxyPair; 147 148 } // namespace net 149 150 #endif // NET_BASE_PROXY_CHAIN_H_ 151