OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
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/proxy/proxy_server.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/basictypes.h" | |
10 #include "base/strings/string_util.h" | |
11 #include "net/base/net_util.h" | |
12 #include "net/http/http_util.h" | |
13 | |
14 namespace net { | |
15 | |
16 namespace { | |
17 | |
18 // Parses the proxy type from a PAC string, to a ProxyServer::Scheme. | |
19 // This mapping is case-insensitive. If no type could be matched | |
20 // returns SCHEME_INVALID. | |
21 ProxyServer::Scheme GetSchemeFromPacTypeInternal( | |
22 std::string::const_iterator begin, | |
23 std::string::const_iterator end) { | |
24 if (LowerCaseEqualsASCII(begin, end, "proxy")) | |
25 return ProxyServer::SCHEME_HTTP; | |
26 if (LowerCaseEqualsASCII(begin, end, "socks")) { | |
27 // Default to v4 for compatibility. This is because the SOCKS4 vs SOCKS5 | |
28 // notation didn't originally exist, so if a client returns SOCKS they | |
29 // really meant SOCKS4. | |
30 return ProxyServer::SCHEME_SOCKS4; | |
31 } | |
32 if (LowerCaseEqualsASCII(begin, end, "socks4")) | |
33 return ProxyServer::SCHEME_SOCKS4; | |
34 if (LowerCaseEqualsASCII(begin, end, "socks5")) | |
35 return ProxyServer::SCHEME_SOCKS5; | |
36 if (LowerCaseEqualsASCII(begin, end, "direct")) | |
37 return ProxyServer::SCHEME_DIRECT; | |
38 if (LowerCaseEqualsASCII(begin, end, "https")) | |
39 return ProxyServer::SCHEME_HTTPS; | |
40 if (LowerCaseEqualsASCII(begin, end, "quic")) | |
41 return ProxyServer::SCHEME_QUIC; | |
42 | |
43 return ProxyServer::SCHEME_INVALID; | |
44 } | |
45 | |
46 // Parses the proxy scheme from a URL-like representation, to a | |
47 // ProxyServer::Scheme. This corresponds with the values used in | |
48 // ProxyServer::ToURI(). If no type could be matched, returns SCHEME_INVALID. | |
49 ProxyServer::Scheme GetSchemeFromURIInternal(std::string::const_iterator begin, | |
50 std::string::const_iterator end) { | |
51 if (LowerCaseEqualsASCII(begin, end, "http")) | |
52 return ProxyServer::SCHEME_HTTP; | |
53 if (LowerCaseEqualsASCII(begin, end, "socks4")) | |
54 return ProxyServer::SCHEME_SOCKS4; | |
55 if (LowerCaseEqualsASCII(begin, end, "socks")) | |
56 return ProxyServer::SCHEME_SOCKS5; | |
57 if (LowerCaseEqualsASCII(begin, end, "socks5")) | |
58 return ProxyServer::SCHEME_SOCKS5; | |
59 if (LowerCaseEqualsASCII(begin, end, "direct")) | |
60 return ProxyServer::SCHEME_DIRECT; | |
61 if (LowerCaseEqualsASCII(begin, end, "https")) | |
62 return ProxyServer::SCHEME_HTTPS; | |
63 if (LowerCaseEqualsASCII(begin, end, "quic")) | |
64 return ProxyServer::SCHEME_QUIC; | |
65 return ProxyServer::SCHEME_INVALID; | |
66 } | |
67 | |
68 } // namespace | |
69 | |
70 ProxyServer::ProxyServer(Scheme scheme, const HostPortPair& host_port_pair) | |
71 : scheme_(scheme), host_port_pair_(host_port_pair) { | |
72 if (scheme_ == SCHEME_DIRECT || scheme_ == SCHEME_INVALID) { | |
73 // |host_port_pair| isn't relevant for these special schemes, so none should | |
74 // have been specified. It is important for this to be consistent since we | |
75 // do raw field comparisons in the equality and comparison functions. | |
76 DCHECK(host_port_pair.Equals(HostPortPair())); | |
77 host_port_pair_ = HostPortPair(); | |
78 } | |
79 } | |
80 | |
81 const HostPortPair& ProxyServer::host_port_pair() const { | |
82 // Doesn't make sense to call this if the URI scheme doesn't | |
83 // have concept of a host. | |
84 DCHECK(is_valid()); | |
85 DCHECK(!is_direct()); | |
86 return host_port_pair_; | |
87 } | |
88 | |
89 // static | |
90 ProxyServer ProxyServer::FromURI(const std::string& uri, | |
91 Scheme default_scheme) { | |
92 return FromURI(uri.begin(), uri.end(), default_scheme); | |
93 } | |
94 | |
95 // static | |
96 ProxyServer ProxyServer::FromURI(std::string::const_iterator begin, | |
97 std::string::const_iterator end, | |
98 Scheme default_scheme) { | |
99 // We will default to |default_scheme| if no scheme specifier was given. | |
100 Scheme scheme = default_scheme; | |
101 | |
102 // Trim the leading/trailing whitespace. | |
103 HttpUtil::TrimLWS(&begin, &end); | |
104 | |
105 // Check for [<scheme> "://"] | |
106 std::string::const_iterator colon = std::find(begin, end, ':'); | |
107 if (colon != end && | |
108 (end - colon) >= 3 && | |
109 *(colon + 1) == '/' && | |
110 *(colon + 2) == '/') { | |
111 scheme = GetSchemeFromURIInternal(begin, colon); | |
112 begin = colon + 3; // Skip past the "://" | |
113 } | |
114 | |
115 // Now parse the <host>[":"<port>]. | |
116 return FromSchemeHostAndPort(scheme, begin, end); | |
117 } | |
118 | |
119 std::string ProxyServer::ToURI() const { | |
120 switch (scheme_) { | |
121 case SCHEME_DIRECT: | |
122 return "direct://"; | |
123 case SCHEME_HTTP: | |
124 // Leave off "http://" since it is our default scheme. | |
125 return host_port_pair().ToString(); | |
126 case SCHEME_SOCKS4: | |
127 return std::string("socks4://") + host_port_pair().ToString(); | |
128 case SCHEME_SOCKS5: | |
129 return std::string("socks5://") + host_port_pair().ToString(); | |
130 case SCHEME_HTTPS: | |
131 return std::string("https://") + host_port_pair().ToString(); | |
132 case SCHEME_QUIC: | |
133 return std::string("quic://") + host_port_pair().ToString(); | |
134 default: | |
135 // Got called with an invalid scheme. | |
136 NOTREACHED(); | |
137 return std::string(); | |
138 } | |
139 } | |
140 | |
141 // static | |
142 ProxyServer ProxyServer::FromPacString(const std::string& pac_string) { | |
143 return FromPacString(pac_string.begin(), pac_string.end()); | |
144 } | |
145 | |
146 // static | |
147 ProxyServer ProxyServer::FromPacString(std::string::const_iterator begin, | |
148 std::string::const_iterator end) { | |
149 // Trim the leading/trailing whitespace. | |
150 HttpUtil::TrimLWS(&begin, &end); | |
151 | |
152 // Input should match: | |
153 // "DIRECT" | ( <type> 1*(LWS) <host-and-port> ) | |
154 | |
155 // Start by finding the first space (if any). | |
156 std::string::const_iterator space; | |
157 for (space = begin; space != end; ++space) { | |
158 if (HttpUtil::IsLWS(*space)) { | |
159 break; | |
160 } | |
161 } | |
162 | |
163 // Everything to the left of the space is the scheme. | |
164 Scheme scheme = GetSchemeFromPacTypeInternal(begin, space); | |
165 | |
166 // And everything to the right of the space is the | |
167 // <host>[":" <port>]. | |
168 return FromSchemeHostAndPort(scheme, space, end); | |
169 } | |
170 | |
171 std::string ProxyServer::ToPacString() const { | |
172 switch (scheme_) { | |
173 case SCHEME_DIRECT: | |
174 return "DIRECT"; | |
175 case SCHEME_HTTP: | |
176 return std::string("PROXY ") + host_port_pair().ToString(); | |
177 case SCHEME_SOCKS4: | |
178 // For compatibility send SOCKS instead of SOCKS4. | |
179 return std::string("SOCKS ") + host_port_pair().ToString(); | |
180 case SCHEME_SOCKS5: | |
181 return std::string("SOCKS5 ") + host_port_pair().ToString(); | |
182 case SCHEME_HTTPS: | |
183 return std::string("HTTPS ") + host_port_pair().ToString(); | |
184 case SCHEME_QUIC: | |
185 return std::string("QUIC ") + host_port_pair().ToString(); | |
186 default: | |
187 // Got called with an invalid scheme. | |
188 NOTREACHED(); | |
189 return std::string(); | |
190 } | |
191 } | |
192 | |
193 // static | |
194 int ProxyServer::GetDefaultPortForScheme(Scheme scheme) { | |
195 switch (scheme) { | |
196 case SCHEME_HTTP: | |
197 return 80; | |
198 case SCHEME_SOCKS4: | |
199 case SCHEME_SOCKS5: | |
200 return 1080; | |
201 case SCHEME_HTTPS: | |
202 case SCHEME_QUIC: | |
203 return 443; | |
204 case SCHEME_INVALID: | |
205 case SCHEME_DIRECT: | |
206 break; | |
207 } | |
208 return -1; | |
209 } | |
210 | |
211 // static | |
212 ProxyServer::Scheme ProxyServer::GetSchemeFromURI(const std::string& scheme) { | |
213 return GetSchemeFromURIInternal(scheme.begin(), scheme.end()); | |
214 } | |
215 | |
216 // static | |
217 ProxyServer ProxyServer::FromSchemeHostAndPort( | |
218 Scheme scheme, | |
219 std::string::const_iterator begin, | |
220 std::string::const_iterator end) { | |
221 | |
222 // Trim leading/trailing space. | |
223 HttpUtil::TrimLWS(&begin, &end); | |
224 | |
225 if (scheme == SCHEME_DIRECT && begin != end) | |
226 return ProxyServer(); // Invalid -- DIRECT cannot have a host/port. | |
227 | |
228 HostPortPair host_port_pair; | |
229 | |
230 if (scheme != SCHEME_INVALID && scheme != SCHEME_DIRECT) { | |
231 std::string host; | |
232 int port = -1; | |
233 // If the scheme has a host/port, parse it. | |
234 bool ok = net::ParseHostAndPort(begin, end, &host, &port); | |
235 if (!ok) | |
236 return ProxyServer(); // Invalid -- failed parsing <host>[":"<port>] | |
237 | |
238 // Choose a default port number if none was given. | |
239 if (port == -1) | |
240 port = GetDefaultPortForScheme(scheme); | |
241 | |
242 host_port_pair = HostPortPair(host, static_cast<uint16>(port)); | |
243 } | |
244 | |
245 return ProxyServer(scheme, host_port_pair); | |
246 } | |
247 | |
248 } // namespace net | |
OLD | NEW |