blob: 3b09f37a48ab37290180053d9cf86af0f28a5433 [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
Eric Orth597399c2021-09-23 17:34:377#include <stdint.h>
8
9#include <ostream>
10#include <string>
11
12#include "base/check_op.h"
13#include "base/numerics/safe_conversions.h"
14#include "base/strings/strcat.h"
15#include "base/strings/string_number_conversions.h"
16#include "base/strings/string_piece.h"
17#include "net/base/proxy_string_util.h"
18#include "third_party/abseil-cpp/absl/types/optional.h"
19#include "url/third_party/mozilla/url_parse.h"
20#include "url/url_canon.h"
21#include "url/url_canon_stdstring.h"
[email protected]f6fb2de2009-02-19 08:11:4222
23namespace net {
24
[email protected]fae7669f2010-08-02 21:49:4025ProxyServer::ProxyServer(Scheme scheme, const HostPortPair& host_port_pair)
26 : scheme_(scheme), host_port_pair_(host_port_pair) {
[email protected]31e68d72010-08-25 06:36:5827 if (scheme_ == SCHEME_DIRECT || 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 }
[email protected]2fbaecf22010-07-22 22:20:3534}
35
Eric Orth597399c2021-09-23 17:34:3736// static
37ProxyServer ProxyServer::FromSchemeHostAndPort(Scheme scheme,
38 base::StringPiece host,
39 base::StringPiece port_str) {
40 // Create INVALID proxies directly using `ProxyServer()`.
41 DCHECK_NE(scheme, SCHEME_INVALID);
42
43 // Create DIRECT proxies directly using `Direct()`.
44 DCHECK_NE(scheme, SCHEME_DIRECT);
45
46 int port_number =
47 url::ParsePort(port_str.data(), url::Component(0, port_str.size()));
48 if (port_number == url::PORT_UNSPECIFIED)
49 return FromSchemeHostAndPort(scheme, host, absl::nullopt);
50 if (port_number == url::PORT_INVALID)
51 return ProxyServer();
52
53 DCHECK(base::IsValueInRangeForNumericType<uint16_t>(port_number));
54
55 return FromSchemeHostAndPort(scheme, host,
56 static_cast<uint16_t>(port_number));
57}
58
59// static
60ProxyServer ProxyServer::FromSchemeHostAndPort(Scheme scheme,
61 base::StringPiece host,
62 absl::optional<uint16_t> port) {
63 // Create INVALID proxies directly using `ProxyServer()`.
64 DCHECK_NE(scheme, SCHEME_INVALID);
65
66 // Create DIRECT proxies directly using `Direct()`.
67 DCHECK_NE(scheme, SCHEME_DIRECT);
68
69 // Add brackets to IPv6 literals if missing, as required by url
70 // canonicalization.
71 std::string bracketed_host;
72 if (!host.empty() && host.front() != '[' &&
73 host.find(":") != base::StringPiece::npos) {
74 bracketed_host = base::StrCat({"[", host, "]"});
75 host = bracketed_host;
76 }
77
78 std::string canonicalized_host;
79 url::StdStringCanonOutput canonicalized_output(&canonicalized_host);
80 url::Component component_output;
81
82 if (!url::CanonicalizeHost(host.data(), url::Component(0, host.size()),
83 &canonicalized_output, &component_output)) {
84 return ProxyServer();
85 }
86 if (!component_output.is_nonempty())
87 return ProxyServer();
88
89 canonicalized_output.Complete();
90
91 // Remove IPv6 literal bracketing, as required by HostPortPair.
92 base::StringPiece unbracketed_host = canonicalized_host;
93 if (canonicalized_host.front() == '[' && canonicalized_host.back() == ']')
94 unbracketed_host = unbracketed_host.substr(1, unbracketed_host.size() - 2);
95
96 // A uint16_t port is always valid and canonicalized.
97 uint16_t fixed_port = port.value_or(GetDefaultPortForScheme(scheme));
98
99 return ProxyServer(scheme, HostPortPair(unbracketed_host, fixed_port));
100}
101
102std::string ProxyServer::GetHost() const {
103 return host_port_pair().HostForURL();
104}
105
106uint16_t ProxyServer::GetPort() const {
107 return host_port_pair().port();
108}
109
[email protected]2fbaecf22010-07-22 22:20:35110const HostPortPair& ProxyServer::host_port_pair() const {
[email protected]f6fb2de2009-02-19 08:11:42111 // Doesn't make sense to call this if the URI scheme doesn't
112 // have concept of a host.
kundaji88ca4112014-09-23 01:35:21113 DCHECK(is_valid());
114 DCHECK(!is_direct());
[email protected]2fbaecf22010-07-22 22:20:35115 return host_port_pair_;
[email protected]2d731a32010-04-29 01:04:06116}
117
[email protected]f6fb2de2009-02-19 08:11:42118// static
[email protected]060313902009-02-19 22:20:22119int ProxyServer::GetDefaultPortForScheme(Scheme scheme) {
120 switch (scheme) {
121 case SCHEME_HTTP:
122 return 80;
123 case SCHEME_SOCKS4:
124 case SCHEME_SOCKS5:
125 return 1080;
[email protected]224c0ad2010-07-20 17:55:53126 case SCHEME_HTTPS:
[email protected]a3c5c07dd2014-02-05 07:38:01127 case SCHEME_QUIC:
[email protected]224c0ad2010-07-20 17:55:53128 return 443;
[email protected]a3c5c07dd2014-02-05 07:38:01129 case SCHEME_INVALID:
130 case SCHEME_DIRECT:
131 break;
[email protected]060313902009-02-19 22:20:22132 }
[email protected]a3c5c07dd2014-02-05 07:38:01133 return -1;
[email protected]060313902009-02-19 22:20:22134}
[email protected]f0a51fb52009-03-05 12:46:38135
Eric Orth597399c2021-09-23 17:34:37136std::ostream& operator<<(std::ostream& os, const ProxyServer& proxy_server) {
137 return os << ProxyServerToPacResultElement(proxy_server);
138}
139
[email protected]f6fb2de2009-02-19 08:11:42140} // namespace net