blob: 9ee7cd213b8f12d0bd7f98eb7ebf276ccbe0ab1d [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_BASE_PROXY_CHAIN_H_
#define NET_BASE_PROXY_CHAIN_H_
#include <stdint.h>
#include <ostream>
#include <string>
#include <tuple>
#include "base/check.h"
#include "base/strings/string_piece.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
#include "net/base/proxy_server.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
// ProxyChain represents a chain of ProxyServers. A chain with multiple proxy
// servers means that a single connection will go through all of the proxies in
// order, using a tunnel through the first proxy to connect to the second, etc.
// A "direct" connection is a chain of length zero.
//
// TODO(crbug.com/1491092): Initial implementations of proxy chaining may, in
// fact, not tunnel through the last proxy in the ProxyChain if the destination
// is http.
//
// TODO(crbug.com/1491092): This does not currently support multi-proxy chains,
// so a ProxyChain is always inter-convertable to a ProxyServer.
class NET_EXPORT ProxyChain {
public:
// Default copy-constructor and assignment operator are OK!
// Constructs an invalid ProxyChain.
ProxyChain() = default;
ProxyChain(ProxyServer::Scheme scheme, const HostPortPair& host_port_pair)
: proxy_server_(scheme, host_port_pair) {}
explicit ProxyChain(ProxyServer proxy_server) : proxy_server_(proxy_server) {}
// Creates a single-proxy ProxyChain, validating and canonicalizing input.
// Port is optional and, if not provided, will be replaced with the default
// port for the given scheme. Accepts IPv6 literal `host`s with surrounding
// brackets (URL format) or without (HostPortPair format). On invalid input,
// result will be a `SCHEME_INVALID` ProxyChain.
//
// Must not be called with `SCHEME_INVALID` or `SCHEME_DIRECT`. Use
// `ProxyChain()` or `Direct()` respectively to create an invalid or direct
// ProxyChain.
static ProxyChain FromSchemeHostAndPort(ProxyServer::Scheme scheme,
base::StringPiece host,
base::StringPiece port_str) {
return ProxyChain(
ProxyServer::FromSchemeHostAndPort(scheme, host, port_str));
}
static ProxyChain FromSchemeHostAndPort(ProxyServer::Scheme scheme,
base::StringPiece host,
absl::optional<uint16_t> port) {
return ProxyChain(ProxyServer::FromSchemeHostAndPort(scheme, host, port));
}
// Create a "direct" proxy chain, which includes no proxy servers.
static ProxyChain Direct() { return ProxyChain(ProxyServer::Direct()); }
// Returns true if this chain contains more than one proxy.
bool is_multi_proxy() const { return false; }
// Returns true if this is a direct (equivalently, zero-proxy) chain.
bool is_direct() const { return proxy_server_.is_direct(); }
// Returns true if this chain is valid.
bool IsValid() const;
bool operator==(const ProxyChain& other) const {
return proxy_server_ == other.proxy_server_;
}
bool operator!=(const ProxyChain& other) const { return !(*this == other); }
// Comparator function so this can be placed in a std::map.
bool operator<(const ProxyChain& other) const {
return proxy_server_ < other.proxy_server_;
}
std::string ToDebugString() const;
// Get the single ProxyServer equivalent to this chain. This must not be
// called for multi-proxy chains.
// TODO(crbug.com/1491092): Remove this method.
const ProxyServer& proxy_server() const {
CHECK(!is_multi_proxy());
return proxy_server_;
}
private:
ProxyServer proxy_server_;
};
NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const ProxyChain& proxy_chain);
} // namespace net
#endif // NET_BASE_PROXY_CHAIN_H_