• 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 <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"
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_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   }
34 }
35 
36 // static
FromSchemeHostAndPort(Scheme scheme,base::StringPiece host,base::StringPiece port_str)37 ProxyServer 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
FromSchemeHostAndPort(Scheme scheme,base::StringPiece host,absl::optional<uint16_t> port)60 ProxyServer 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_empty())
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 
GetHost() const102 std::string ProxyServer::GetHost() const {
103   return host_port_pair().HostForURL();
104 }
105 
GetPort() const106 uint16_t ProxyServer::GetPort() const {
107   return host_port_pair().port();
108 }
109 
host_port_pair() const110 const HostPortPair& ProxyServer::host_port_pair() const {
111   // Doesn't make sense to call this if the URI scheme doesn't
112   // have concept of a host.
113   DCHECK(is_valid());
114   DCHECK(!is_direct());
115   return host_port_pair_;
116 }
117 
118 // static
GetDefaultPortForScheme(Scheme scheme)119 int 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;
126     case SCHEME_HTTPS:
127     case SCHEME_QUIC:
128       return 443;
129     case SCHEME_INVALID:
130     case SCHEME_DIRECT:
131       break;
132   }
133   return -1;
134 }
135 
operator <<(std::ostream & os,const ProxyServer & proxy_server)136 std::ostream& operator<<(std::ostream& os, const ProxyServer& proxy_server) {
137   return os << ProxyServerToPacResultElement(proxy_server);
138 }
139 
140 }  // namespace net
141