| 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 |