blob: f3050bf419b2a34c9954b7b8473c761dfa82746d [file] [log] [blame]
[email protected]2fbaecf22010-07-22 22:20:351// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]f6fb2de2009-02-19 08:11:422// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Lily Houghton582d4622018-01-22 22:43:405#include "net/base/proxy_server.h"
[email protected]f6fb2de2009-02-19 08:11:426
[email protected]4b80a752009-02-19 08:51:457#include <algorithm>
8
[email protected]fc9be5802013-06-11 10:56:519#include "base/strings/string_util.h"
xunjieliec84e4e2017-02-09 22:04:1510#include "base/trace_event/memory_usage_estimator.h"
tfarina7a4a7fd2016-01-20 14:23:4411#include "net/base/url_util.h"
[email protected]f6fb2de2009-02-19 08:11:4212#include "net/http/http_util.h"
13
14namespace net {
15
16namespace {
17
[email protected]e84925d2011-02-09 16:29:3318// Parses the proxy type from a PAC string, to a ProxyServer::Scheme.
[email protected]f6fb2de2009-02-19 08:11:4219// This mapping is case-insensitive. If no type could be matched
20// returns SCHEME_INVALID.
brettw85111672015-07-23 21:56:3521ProxyServer::Scheme GetSchemeFromPacTypeInternal(base::StringPiece type) {
22 if (base::LowerCaseEqualsASCII(type, "proxy"))
[email protected]f6fb2de2009-02-19 08:11:4223 return ProxyServer::SCHEME_HTTP;
brettw85111672015-07-23 21:56:3524 if (base::LowerCaseEqualsASCII(type, "socks")) {
[email protected]f6fb2de2009-02-19 08:11:4225 // Default to v4 for compatibility. This is because the SOCKS4 vs SOCKS5
26 // notation didn't originally exist, so if a client returns SOCKS they
27 // really meant SOCKS4.
28 return ProxyServer::SCHEME_SOCKS4;
29 }
brettw85111672015-07-23 21:56:3530 if (base::LowerCaseEqualsASCII(type, "socks4"))
[email protected]f6fb2de2009-02-19 08:11:4231 return ProxyServer::SCHEME_SOCKS4;
brettw85111672015-07-23 21:56:3532 if (base::LowerCaseEqualsASCII(type, "socks5"))
[email protected]f6fb2de2009-02-19 08:11:4233 return ProxyServer::SCHEME_SOCKS5;
brettw85111672015-07-23 21:56:3534 if (base::LowerCaseEqualsASCII(type, "direct"))
[email protected]f6fb2de2009-02-19 08:11:4235 return ProxyServer::SCHEME_DIRECT;
brettw85111672015-07-23 21:56:3536 if (base::LowerCaseEqualsASCII(type, "https"))
[email protected]224c0ad2010-07-20 17:55:5337 return ProxyServer::SCHEME_HTTPS;
brettw85111672015-07-23 21:56:3538 if (base::LowerCaseEqualsASCII(type, "quic"))
[email protected]a3c5c07dd2014-02-05 07:38:0139 return ProxyServer::SCHEME_QUIC;
[email protected]f6fb2de2009-02-19 08:11:4240
41 return ProxyServer::SCHEME_INVALID;
42}
43
[email protected]e84925d2011-02-09 16:29:3344// Parses the proxy scheme from a URL-like representation, to a
45// ProxyServer::Scheme. This corresponds with the values used in
[email protected]f6fb2de2009-02-19 08:11:4246// ProxyServer::ToURI(). If no type could be matched, returns SCHEME_INVALID.
brettw85111672015-07-23 21:56:3547ProxyServer::Scheme GetSchemeFromURIInternal(base::StringPiece type) {
48 if (base::LowerCaseEqualsASCII(type, "http"))
[email protected]f6fb2de2009-02-19 08:11:4249 return ProxyServer::SCHEME_HTTP;
brettw85111672015-07-23 21:56:3550 if (base::LowerCaseEqualsASCII(type, "socks4"))
[email protected]f6fb2de2009-02-19 08:11:4251 return ProxyServer::SCHEME_SOCKS4;
brettw85111672015-07-23 21:56:3552 if (base::LowerCaseEqualsASCII(type, "socks"))
[email protected]6be52b92010-09-27 19:13:3653 return ProxyServer::SCHEME_SOCKS5;
brettw85111672015-07-23 21:56:3554 if (base::LowerCaseEqualsASCII(type, "socks5"))
[email protected]f6fb2de2009-02-19 08:11:4255 return ProxyServer::SCHEME_SOCKS5;
brettw85111672015-07-23 21:56:3556 if (base::LowerCaseEqualsASCII(type, "direct"))
[email protected]f6fb2de2009-02-19 08:11:4257 return ProxyServer::SCHEME_DIRECT;
brettw85111672015-07-23 21:56:3558 if (base::LowerCaseEqualsASCII(type, "https"))
[email protected]224c0ad2010-07-20 17:55:5359 return ProxyServer::SCHEME_HTTPS;
brettw85111672015-07-23 21:56:3560 if (base::LowerCaseEqualsASCII(type, "quic"))
[email protected]a3c5c07dd2014-02-05 07:38:0161 return ProxyServer::SCHEME_QUIC;
[email protected]f6fb2de2009-02-19 08:11:4262 return ProxyServer::SCHEME_INVALID;
63}
64
65} // namespace
66
[email protected]fae7669f2010-08-02 21:49:4067ProxyServer::ProxyServer(Scheme scheme, const HostPortPair& host_port_pair)
68 : scheme_(scheme), host_port_pair_(host_port_pair) {
[email protected]31e68d72010-08-25 06:36:5869 if (scheme_ == SCHEME_DIRECT || scheme_ == SCHEME_INVALID) {
70 // |host_port_pair| isn't relevant for these special schemes, so none should
71 // have been specified. It is important for this to be consistent since we
72 // do raw field comparisons in the equality and comparison functions.
73 DCHECK(host_port_pair.Equals(HostPortPair()));
74 host_port_pair_ = HostPortPair();
75 }
[email protected]2fbaecf22010-07-22 22:20:3576}
77
78const HostPortPair& ProxyServer::host_port_pair() const {
[email protected]f6fb2de2009-02-19 08:11:4279 // Doesn't make sense to call this if the URI scheme doesn't
80 // have concept of a host.
kundaji88ca4112014-09-23 01:35:2181 DCHECK(is_valid());
82 DCHECK(!is_direct());
[email protected]2fbaecf22010-07-22 22:20:3583 return host_port_pair_;
[email protected]2d731a32010-04-29 01:04:0684}
85
[email protected]f6fb2de2009-02-19 08:11:4286// static
[email protected]87a102b2009-07-14 05:23:3087ProxyServer ProxyServer::FromURI(const std::string& uri,
88 Scheme default_scheme) {
89 return FromURI(uri.begin(), uri.end(), default_scheme);
[email protected]f6fb2de2009-02-19 08:11:4290}
91
92// static
93ProxyServer ProxyServer::FromURI(std::string::const_iterator begin,
[email protected]87a102b2009-07-14 05:23:3094 std::string::const_iterator end,
95 Scheme default_scheme) {
96 // We will default to |default_scheme| if no scheme specifier was given.
97 Scheme scheme = default_scheme;
[email protected]f6fb2de2009-02-19 08:11:4298
99 // Trim the leading/trailing whitespace.
100 HttpUtil::TrimLWS(&begin, &end);
101
102 // Check for [<scheme> "://"]
103 std::string::const_iterator colon = std::find(begin, end, ':');
104 if (colon != end &&
105 (end - colon) >= 3 &&
106 *(colon + 1) == '/' &&
107 *(colon + 2) == '/') {
brettw85111672015-07-23 21:56:35108 scheme = GetSchemeFromURIInternal(base::StringPiece(begin, colon));
[email protected]f6fb2de2009-02-19 08:11:42109 begin = colon + 3; // Skip past the "://"
110 }
111
112 // Now parse the <host>[":"<port>].
113 return FromSchemeHostAndPort(scheme, begin, end);
114}
115
116std::string ProxyServer::ToURI() const {
117 switch (scheme_) {
118 case SCHEME_DIRECT:
119 return "direct://";
120 case SCHEME_HTTP:
121 // Leave off "http://" since it is our default scheme.
[email protected]2fbaecf22010-07-22 22:20:35122 return host_port_pair().ToString();
[email protected]f6fb2de2009-02-19 08:11:42123 case SCHEME_SOCKS4:
[email protected]2fbaecf22010-07-22 22:20:35124 return std::string("socks4://") + host_port_pair().ToString();
[email protected]f6fb2de2009-02-19 08:11:42125 case SCHEME_SOCKS5:
[email protected]2fbaecf22010-07-22 22:20:35126 return std::string("socks5://") + host_port_pair().ToString();
[email protected]224c0ad2010-07-20 17:55:53127 case SCHEME_HTTPS:
[email protected]2fbaecf22010-07-22 22:20:35128 return std::string("https://") + host_port_pair().ToString();
[email protected]a3c5c07dd2014-02-05 07:38:01129 case SCHEME_QUIC:
130 return std::string("quic://") + host_port_pair().ToString();
[email protected]f6fb2de2009-02-19 08:11:42131 default:
132 // Got called with an invalid scheme.
133 NOTREACHED();
134 return std::string();
135 }
136}
137
138// static
139ProxyServer ProxyServer::FromPacString(const std::string& pac_string) {
140 return FromPacString(pac_string.begin(), pac_string.end());
141}
142
[email protected]aacc8f12010-06-23 17:24:40143// static
[email protected]f6fb2de2009-02-19 08:11:42144ProxyServer ProxyServer::FromPacString(std::string::const_iterator begin,
145 std::string::const_iterator end) {
146 // Trim the leading/trailing whitespace.
147 HttpUtil::TrimLWS(&begin, &end);
148
149 // Input should match:
150 // "DIRECT" | ( <type> 1*(LWS) <host-and-port> )
151
152 // Start by finding the first space (if any).
153 std::string::const_iterator space;
154 for (space = begin; space != end; ++space) {
155 if (HttpUtil::IsLWS(*space)) {
156 break;
157 }
158 }
159
160 // Everything to the left of the space is the scheme.
brettw85111672015-07-23 21:56:35161 Scheme scheme = GetSchemeFromPacTypeInternal(base::StringPiece(begin, space));
[email protected]f6fb2de2009-02-19 08:11:42162
163 // And everything to the right of the space is the
164 // <host>[":" <port>].
165 return FromSchemeHostAndPort(scheme, space, end);
166}
167
168std::string ProxyServer::ToPacString() const {
brettw85111672015-07-23 21:56:35169 switch (scheme_) {
[email protected]f6fb2de2009-02-19 08:11:42170 case SCHEME_DIRECT:
171 return "DIRECT";
172 case SCHEME_HTTP:
[email protected]2fbaecf22010-07-22 22:20:35173 return std::string("PROXY ") + host_port_pair().ToString();
[email protected]f6fb2de2009-02-19 08:11:42174 case SCHEME_SOCKS4:
175 // For compatibility send SOCKS instead of SOCKS4.
[email protected]2fbaecf22010-07-22 22:20:35176 return std::string("SOCKS ") + host_port_pair().ToString();
[email protected]f6fb2de2009-02-19 08:11:42177 case SCHEME_SOCKS5:
[email protected]2fbaecf22010-07-22 22:20:35178 return std::string("SOCKS5 ") + host_port_pair().ToString();
[email protected]224c0ad2010-07-20 17:55:53179 case SCHEME_HTTPS:
[email protected]2fbaecf22010-07-22 22:20:35180 return std::string("HTTPS ") + host_port_pair().ToString();
[email protected]a3c5c07dd2014-02-05 07:38:01181 case SCHEME_QUIC:
182 return std::string("QUIC ") + host_port_pair().ToString();
[email protected]f6fb2de2009-02-19 08:11:42183 default:
184 // Got called with an invalid scheme.
185 NOTREACHED();
186 return std::string();
187 }
188}
189
190// static
[email protected]060313902009-02-19 22:20:22191int ProxyServer::GetDefaultPortForScheme(Scheme scheme) {
192 switch (scheme) {
193 case SCHEME_HTTP:
194 return 80;
195 case SCHEME_SOCKS4:
196 case SCHEME_SOCKS5:
197 return 1080;
[email protected]224c0ad2010-07-20 17:55:53198 case SCHEME_HTTPS:
[email protected]a3c5c07dd2014-02-05 07:38:01199 case SCHEME_QUIC:
[email protected]224c0ad2010-07-20 17:55:53200 return 443;
[email protected]a3c5c07dd2014-02-05 07:38:01201 case SCHEME_INVALID:
202 case SCHEME_DIRECT:
203 break;
[email protected]060313902009-02-19 22:20:22204 }
[email protected]a3c5c07dd2014-02-05 07:38:01205 return -1;
[email protected]060313902009-02-19 22:20:22206}
[email protected]f0a51fb52009-03-05 12:46:38207
[email protected]060313902009-02-19 22:20:22208// static
[email protected]e84925d2011-02-09 16:29:33209ProxyServer::Scheme ProxyServer::GetSchemeFromURI(const std::string& scheme) {
brettw85111672015-07-23 21:56:35210 return GetSchemeFromURIInternal(scheme);
[email protected]e84925d2011-02-09 16:29:33211}
212
xunjieliec84e4e2017-02-09 22:04:15213size_t ProxyServer::EstimateMemoryUsage() const {
214 return base::trace_event::EstimateMemoryUsage(host_port_pair_);
215}
216
[email protected]e84925d2011-02-09 16:29:33217// static
[email protected]f6fb2de2009-02-19 08:11:42218ProxyServer ProxyServer::FromSchemeHostAndPort(
219 Scheme scheme,
220 std::string::const_iterator begin,
221 std::string::const_iterator end) {
222
223 // Trim leading/trailing space.
224 HttpUtil::TrimLWS(&begin, &end);
225
226 if (scheme == SCHEME_DIRECT && begin != end)
227 return ProxyServer(); // Invalid -- DIRECT cannot have a host/port.
228
[email protected]31e68d72010-08-25 06:36:58229 HostPortPair host_port_pair;
[email protected]f6fb2de2009-02-19 08:11:42230
231 if (scheme != SCHEME_INVALID && scheme != SCHEME_DIRECT) {
[email protected]31e68d72010-08-25 06:36:58232 std::string host;
233 int port = -1;
[email protected]f6fb2de2009-02-19 08:11:42234 // If the scheme has a host/port, parse it.
ttuttle859dc7a2015-04-23 19:42:29235 bool ok = ParseHostAndPort(begin, end, &host, &port);
[email protected]f6fb2de2009-02-19 08:11:42236 if (!ok)
237 return ProxyServer(); // Invalid -- failed parsing <host>[":"<port>]
[email protected]31e68d72010-08-25 06:36:58238
239 // Choose a default port number if none was given.
240 if (port == -1)
241 port = GetDefaultPortForScheme(scheme);
242
Avi Drissman13fc8932015-12-20 04:40:46243 host_port_pair = HostPortPair(host, static_cast<uint16_t>(port));
[email protected]f6fb2de2009-02-19 08:11:42244 }
245
[email protected]31e68d72010-08-25 06:36:58246 return ProxyServer(scheme, host_port_pair);
[email protected]f6fb2de2009-02-19 08:11:42247}
248
249} // namespace net