• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/pickle.h"
17 #include "base/strings/strcat.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "net/base/proxy_string_util.h"
21 #include "url/third_party/mozilla/url_parse.h"
22 #include "url/url_canon.h"
23 #include "url/url_canon_stdstring.h"
24 
25 namespace net {
26 
27 namespace {
28 
IsValidSchemeInt(int scheme_int)29 bool IsValidSchemeInt(int scheme_int) {
30   switch (scheme_int) {
31     case ProxyServer::SCHEME_INVALID:
32     case ProxyServer::SCHEME_HTTP:
33     case ProxyServer::SCHEME_SOCKS4:
34     case ProxyServer::SCHEME_SOCKS5:
35     case ProxyServer::SCHEME_HTTPS:
36     case ProxyServer::SCHEME_QUIC:
37       return true;
38     default:
39       return false;
40   }
41 }
42 
43 }  // namespace
44 
ProxyServer(Scheme scheme,const HostPortPair & host_port_pair)45 ProxyServer::ProxyServer(Scheme scheme, const HostPortPair& host_port_pair)
46       : scheme_(scheme), host_port_pair_(host_port_pair) {
47   if (scheme_ == SCHEME_INVALID) {
48     // |host_port_pair| isn't relevant for these special schemes, so none should
49     // have been specified. It is important for this to be consistent since we
50     // do raw field comparisons in the equality and comparison functions.
51     DCHECK(host_port_pair.Equals(HostPortPair()));
52     host_port_pair_ = HostPortPair();
53   }
54 }
55 
56 // static
FromSchemeHostAndPort(Scheme scheme,std::string_view host,std::string_view port_str)57 ProxyServer ProxyServer::FromSchemeHostAndPort(Scheme scheme,
58                                                std::string_view host,
59                                                std::string_view port_str) {
60   // Create INVALID proxies directly using `ProxyServer()`.
61   DCHECK_NE(scheme, SCHEME_INVALID);
62 
63   int port_number =
64       url::ParsePort(port_str.data(), url::Component(0, port_str.size()));
65   if (port_number == url::PORT_UNSPECIFIED)
66     return FromSchemeHostAndPort(scheme, host, std::nullopt);
67   if (port_number == url::PORT_INVALID)
68     return ProxyServer();
69 
70   DCHECK(base::IsValueInRangeForNumericType<uint16_t>(port_number));
71 
72   return FromSchemeHostAndPort(scheme, host,
73                                static_cast<uint16_t>(port_number));
74 }
75 
76 // static
FromSchemeHostAndPort(Scheme scheme,std::string_view host,std::optional<uint16_t> port)77 ProxyServer ProxyServer::FromSchemeHostAndPort(Scheme scheme,
78                                                std::string_view host,
79                                                std::optional<uint16_t> port) {
80   // Create INVALID proxies directly using `ProxyServer()`.
81   DCHECK_NE(scheme, SCHEME_INVALID);
82 
83   // Trim host which may have been pasted with excess whitespace.
84   if (!host.empty()) {
85     host = base::TrimWhitespaceASCII(host, base::TRIM_ALL);
86   }
87 
88   // Add brackets to IPv6 literals if missing, as required by url
89   // canonicalization.
90   std::string bracketed_host;
91   if (!host.empty() && host.front() != '[' &&
92       host.find(":") != std::string_view::npos) {
93     bracketed_host = base::StrCat({"[", host, "]"});
94     host = bracketed_host;
95   }
96 
97   std::string canonicalized_host;
98   url::StdStringCanonOutput canonicalized_output(&canonicalized_host);
99   url::Component component_output;
100 
101   if (!url::CanonicalizeHost(host.data(), url::Component(0, host.size()),
102                              &canonicalized_output, &component_output)) {
103     return ProxyServer();
104   }
105   if (component_output.is_empty())
106     return ProxyServer();
107 
108   canonicalized_output.Complete();
109 
110   // Remove IPv6 literal bracketing, as required by HostPortPair.
111   std::string_view unbracketed_host = canonicalized_host;
112   if (canonicalized_host.front() == '[' && canonicalized_host.back() == ']')
113     unbracketed_host = unbracketed_host.substr(1, unbracketed_host.size() - 2);
114 
115   // A uint16_t port is always valid and canonicalized.
116   uint16_t fixed_port = port.value_or(GetDefaultPortForScheme(scheme));
117 
118   return ProxyServer(scheme, HostPortPair(unbracketed_host, fixed_port));
119 }
120 
121 // static
CreateFromPickle(base::PickleIterator * pickle_iter)122 ProxyServer ProxyServer::CreateFromPickle(base::PickleIterator* pickle_iter) {
123   Scheme scheme = SCHEME_INVALID;
124   int scheme_int;
125   if (pickle_iter->ReadInt(&scheme_int) && IsValidSchemeInt(scheme_int)) {
126     scheme = static_cast<Scheme>(scheme_int);
127   }
128 
129   HostPortPair host_port_pair;
130   std::string host_port_pair_string;
131   if (pickle_iter->ReadString(&host_port_pair_string)) {
132     host_port_pair = HostPortPair::FromString(host_port_pair_string);
133   }
134 
135   return ProxyServer(scheme, host_port_pair);
136 }
137 
Persist(base::Pickle * pickle) const138 void ProxyServer::Persist(base::Pickle* pickle) const {
139   pickle->WriteInt(static_cast<int>(scheme_));
140   pickle->WriteString(host_port_pair_.ToString());
141 }
142 
GetHost() const143 std::string ProxyServer::GetHost() const {
144   return host_port_pair().HostForURL();
145 }
146 
GetPort() const147 uint16_t ProxyServer::GetPort() const {
148   return host_port_pair().port();
149 }
150 
host_port_pair() const151 const HostPortPair& ProxyServer::host_port_pair() const {
152   // Doesn't make sense to call this if the URI scheme doesn't
153   // have concept of a host.
154   DCHECK(is_valid());
155   return host_port_pair_;
156 }
157 
158 // static
GetDefaultPortForScheme(Scheme scheme)159 int ProxyServer::GetDefaultPortForScheme(Scheme scheme) {
160   switch (scheme) {
161     case SCHEME_HTTP:
162       return 80;
163     case SCHEME_SOCKS4:
164     case SCHEME_SOCKS5:
165       return 1080;
166     case SCHEME_HTTPS:
167     case SCHEME_QUIC:
168       return 443;
169     case SCHEME_INVALID:
170       break;
171   }
172   return -1;
173 }
174 
operator <<(std::ostream & os,const ProxyServer & proxy_server)175 std::ostream& operator<<(std::ostream& os, const ProxyServer& proxy_server) {
176   return os << ProxyServerToPacResultElement(proxy_server);
177 }
178 
179 }  // namespace net
180