xref: /aosp_15_r20/external/cronet/net/base/proxy_server.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2010 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/base/proxy_server.h"
6 
7 #include <stdint.h>
8 
9 #include <optional>
10 #include <ostream>
11 #include <string>
12 #include <string_view>
13 
14 #include "base/check_op.h"
15 #include "base/numerics/safe_conversions.h"
16 #include "base/strings/strcat.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "net/base/proxy_string_util.h"
19 #include "url/third_party/mozilla/url_parse.h"
20 #include "url/url_canon.h"
21 #include "url/url_canon_stdstring.h"
22 
23 namespace net {
24 
ProxyServer(Scheme scheme,const HostPortPair & host_port_pair)25 ProxyServer::ProxyServer(Scheme scheme, const HostPortPair& host_port_pair)
26       : scheme_(scheme), host_port_pair_(host_port_pair) {
27   if (scheme_ == SCHEME_INVALID) {
28     // |host_port_pair| isn't relevant for these special schemes, so none should
29     // have been specified. It is important for this to be consistent since we
30     // do raw field comparisons in the equality and comparison functions.
31     DCHECK(host_port_pair.Equals(HostPortPair()));
32     host_port_pair_ = HostPortPair();
33   }
34 }
35 
36 // static
FromSchemeHostAndPort(Scheme scheme,std::string_view host,std::string_view port_str)37 ProxyServer ProxyServer::FromSchemeHostAndPort(Scheme scheme,
38                                                std::string_view host,
39                                                std::string_view port_str) {
40   // Create INVALID proxies directly using `ProxyServer()`.
41   DCHECK_NE(scheme, SCHEME_INVALID);
42 
43   int port_number =
44       url::ParsePort(port_str.data(), url::Component(0, port_str.size()));
45   if (port_number == url::PORT_UNSPECIFIED)
46     return FromSchemeHostAndPort(scheme, host, std::nullopt);
47   if (port_number == url::PORT_INVALID)
48     return ProxyServer();
49 
50   DCHECK(base::IsValueInRangeForNumericType<uint16_t>(port_number));
51 
52   return FromSchemeHostAndPort(scheme, host,
53                                static_cast<uint16_t>(port_number));
54 }
55 
56 // static
FromSchemeHostAndPort(Scheme scheme,std::string_view host,std::optional<uint16_t> port)57 ProxyServer ProxyServer::FromSchemeHostAndPort(Scheme scheme,
58                                                std::string_view host,
59                                                std::optional<uint16_t> port) {
60   // Create INVALID proxies directly using `ProxyServer()`.
61   DCHECK_NE(scheme, SCHEME_INVALID);
62 
63   // Add brackets to IPv6 literals if missing, as required by url
64   // canonicalization.
65   std::string bracketed_host;
66   if (!host.empty() && host.front() != '[' &&
67       host.find(":") != std::string_view::npos) {
68     bracketed_host = base::StrCat({"[", host, "]"});
69     host = bracketed_host;
70   }
71 
72   std::string canonicalized_host;
73   url::StdStringCanonOutput canonicalized_output(&canonicalized_host);
74   url::Component component_output;
75 
76   if (!url::CanonicalizeHost(host.data(), url::Component(0, host.size()),
77                              &canonicalized_output, &component_output)) {
78     return ProxyServer();
79   }
80   if (component_output.is_empty())
81     return ProxyServer();
82 
83   canonicalized_output.Complete();
84 
85   // Remove IPv6 literal bracketing, as required by HostPortPair.
86   std::string_view unbracketed_host = canonicalized_host;
87   if (canonicalized_host.front() == '[' && canonicalized_host.back() == ']')
88     unbracketed_host = unbracketed_host.substr(1, unbracketed_host.size() - 2);
89 
90   // A uint16_t port is always valid and canonicalized.
91   uint16_t fixed_port = port.value_or(GetDefaultPortForScheme(scheme));
92 
93   return ProxyServer(scheme, HostPortPair(unbracketed_host, fixed_port));
94 }
95 
GetHost() const96 std::string ProxyServer::GetHost() const {
97   return host_port_pair().HostForURL();
98 }
99 
GetPort() const100 uint16_t ProxyServer::GetPort() const {
101   return host_port_pair().port();
102 }
103 
host_port_pair() const104 const HostPortPair& ProxyServer::host_port_pair() const {
105   // Doesn't make sense to call this if the URI scheme doesn't
106   // have concept of a host.
107   DCHECK(is_valid());
108   return host_port_pair_;
109 }
110 
111 // static
GetDefaultPortForScheme(Scheme scheme)112 int ProxyServer::GetDefaultPortForScheme(Scheme scheme) {
113   switch (scheme) {
114     case SCHEME_HTTP:
115       return 80;
116     case SCHEME_SOCKS4:
117     case SCHEME_SOCKS5:
118       return 1080;
119     case SCHEME_HTTPS:
120     case SCHEME_QUIC:
121       return 443;
122     case SCHEME_INVALID:
123       break;
124   }
125   return -1;
126 }
127 
operator <<(std::ostream & os,const ProxyServer & proxy_server)128 std::ostream& operator<<(std::ostream& os, const ProxyServer& proxy_server) {
129   return os << ProxyServerToPacResultElement(proxy_server);
130 }
131 
132 }  // namespace net
133