blob: a8d12fcb6807cbf8ae15502accbee09ada0777a3 [file] [log] [blame]
[email protected]d51365e2013-11-27 10:46:521// Copyright 2013 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/websockets/websocket_basic_handshake_stream.h"
6
7#include <algorithm>
8#include <iterator>
[email protected]0be93922014-01-29 00:42:459#include <set>
[email protected]96868202014-01-09 10:38:0410#include <string>
[email protected]cd48ed12014-01-22 14:34:2211#include <vector>
[email protected]d51365e2013-11-27 10:46:5212
13#include "base/base64.h"
14#include "base/basictypes.h"
15#include "base/bind.h"
16#include "base/containers/hash_tables.h"
17#include "base/stl_util.h"
[email protected]0be93922014-01-29 00:42:4518#include "base/strings/string_number_conversions.h"
[email protected]d51365e2013-11-27 10:46:5219#include "base/strings/string_util.h"
[email protected]96868202014-01-09 10:38:0420#include "base/strings/stringprintf.h"
[email protected]cd48ed12014-01-22 14:34:2221#include "base/time/time.h"
[email protected]d51365e2013-11-27 10:46:5222#include "crypto/random.h"
23#include "net/http/http_request_headers.h"
24#include "net/http/http_request_info.h"
25#include "net/http/http_response_body_drainer.h"
26#include "net/http/http_response_headers.h"
27#include "net/http/http_status_code.h"
28#include "net/http/http_stream_parser.h"
29#include "net/socket/client_socket_handle.h"
30#include "net/websockets/websocket_basic_stream.h"
[email protected]0be93922014-01-29 00:42:4531#include "net/websockets/websocket_deflate_predictor.h"
32#include "net/websockets/websocket_deflate_predictor_impl.h"
33#include "net/websockets/websocket_deflate_stream.h"
34#include "net/websockets/websocket_deflater.h"
[email protected]96868202014-01-09 10:38:0435#include "net/websockets/websocket_extension_parser.h"
[email protected]d51365e2013-11-27 10:46:5236#include "net/websockets/websocket_handshake_constants.h"
37#include "net/websockets/websocket_handshake_handler.h"
[email protected]cd48ed12014-01-22 14:34:2238#include "net/websockets/websocket_handshake_request_info.h"
39#include "net/websockets/websocket_handshake_response_info.h"
[email protected]d51365e2013-11-27 10:46:5240#include "net/websockets/websocket_stream.h"
41
42namespace net {
[email protected]0be93922014-01-29 00:42:4543
44// TODO(ricea): If more extensions are added, replace this with a more general
45// mechanism.
46struct WebSocketExtensionParams {
47 WebSocketExtensionParams()
48 : deflate_enabled(false),
49 client_window_bits(15),
50 deflate_mode(WebSocketDeflater::TAKE_OVER_CONTEXT) {}
51
52 bool deflate_enabled;
53 int client_window_bits;
54 WebSocketDeflater::ContextTakeOverMode deflate_mode;
55};
56
[email protected]d51365e2013-11-27 10:46:5257namespace {
58
[email protected]96868202014-01-09 10:38:0459enum GetHeaderResult {
60 GET_HEADER_OK,
61 GET_HEADER_MISSING,
62 GET_HEADER_MULTIPLE,
63};
64
65std::string MissingHeaderMessage(const std::string& header_name) {
66 return std::string("'") + header_name + "' header is missing";
67}
68
69std::string MultipleHeaderValuesMessage(const std::string& header_name) {
70 return
71 std::string("'") +
72 header_name +
73 "' header must not appear more than once in a response";
74}
75
[email protected]d51365e2013-11-27 10:46:5276std::string GenerateHandshakeChallenge() {
77 std::string raw_challenge(websockets::kRawChallengeLength, '\0');
78 crypto::RandBytes(string_as_array(&raw_challenge), raw_challenge.length());
79 std::string encoded_challenge;
[email protected]33fca122013-12-11 01:48:5080 base::Base64Encode(raw_challenge, &encoded_challenge);
[email protected]d51365e2013-11-27 10:46:5281 return encoded_challenge;
82}
83
84void AddVectorHeaderIfNonEmpty(const char* name,
85 const std::vector<std::string>& value,
86 HttpRequestHeaders* headers) {
87 if (value.empty())
88 return;
89 headers->SetHeader(name, JoinString(value, ", "));
90}
91
[email protected]96868202014-01-09 10:38:0492GetHeaderResult GetSingleHeaderValue(const HttpResponseHeaders* headers,
93 const base::StringPiece& name,
94 std::string* value) {
[email protected]d51365e2013-11-27 10:46:5295 void* state = NULL;
[email protected]96868202014-01-09 10:38:0496 size_t num_values = 0;
97 std::string temp_value;
98 while (headers->EnumerateHeader(&state, name, &temp_value)) {
99 if (++num_values > 1)
100 return GET_HEADER_MULTIPLE;
101 *value = temp_value;
[email protected]d51365e2013-11-27 10:46:52102 }
[email protected]96868202014-01-09 10:38:04103 return num_values > 0 ? GET_HEADER_OK : GET_HEADER_MISSING;
104}
105
106bool ValidateHeaderHasSingleValue(GetHeaderResult result,
107 const std::string& header_name,
108 std::string* failure_message) {
109 if (result == GET_HEADER_MISSING) {
110 *failure_message = MissingHeaderMessage(header_name);
111 return false;
112 }
113 if (result == GET_HEADER_MULTIPLE) {
114 *failure_message = MultipleHeaderValuesMessage(header_name);
115 return false;
116 }
117 DCHECK_EQ(result, GET_HEADER_OK);
118 return true;
119}
120
121bool ValidateUpgrade(const HttpResponseHeaders* headers,
122 std::string* failure_message) {
123 std::string value;
124 GetHeaderResult result =
125 GetSingleHeaderValue(headers, websockets::kUpgrade, &value);
126 if (!ValidateHeaderHasSingleValue(result,
127 websockets::kUpgrade,
128 failure_message)) {
129 return false;
130 }
131
132 if (!LowerCaseEqualsASCII(value, websockets::kWebSocketLowercase)) {
133 *failure_message =
134 "'Upgrade' header value is not 'WebSocket': " + value;
135 return false;
136 }
137 return true;
138}
139
140bool ValidateSecWebSocketAccept(const HttpResponseHeaders* headers,
141 const std::string& expected,
142 std::string* failure_message) {
143 std::string actual;
144 GetHeaderResult result =
145 GetSingleHeaderValue(headers, websockets::kSecWebSocketAccept, &actual);
146 if (!ValidateHeaderHasSingleValue(result,
147 websockets::kSecWebSocketAccept,
148 failure_message)) {
149 return false;
150 }
151
152 if (expected != actual) {
153 *failure_message = "Incorrect 'Sec-WebSocket-Accept' header value";
154 return false;
155 }
156 return true;
157}
158
159bool ValidateConnection(const HttpResponseHeaders* headers,
160 std::string* failure_message) {
161 // Connection header is permitted to contain other tokens.
162 if (!headers->HasHeader(HttpRequestHeaders::kConnection)) {
163 *failure_message = MissingHeaderMessage(HttpRequestHeaders::kConnection);
164 return false;
165 }
166 if (!headers->HasHeaderValue(HttpRequestHeaders::kConnection,
167 websockets::kUpgrade)) {
168 *failure_message = "'Connection' header value must contain 'Upgrade'";
169 return false;
170 }
171 return true;
[email protected]d51365e2013-11-27 10:46:52172}
173
174bool ValidateSubProtocol(
[email protected]96868202014-01-09 10:38:04175 const HttpResponseHeaders* headers,
[email protected]d51365e2013-11-27 10:46:52176 const std::vector<std::string>& requested_sub_protocols,
[email protected]96868202014-01-09 10:38:04177 std::string* sub_protocol,
178 std::string* failure_message) {
[email protected]d51365e2013-11-27 10:46:52179 void* state = NULL;
[email protected]96868202014-01-09 10:38:04180 std::string value;
[email protected]d51365e2013-11-27 10:46:52181 base::hash_set<std::string> requested_set(requested_sub_protocols.begin(),
182 requested_sub_protocols.end());
[email protected]96868202014-01-09 10:38:04183 int count = 0;
184 bool has_multiple_protocols = false;
185 bool has_invalid_protocol = false;
[email protected]d51365e2013-11-27 10:46:52186
[email protected]96868202014-01-09 10:38:04187 while (!has_invalid_protocol || !has_multiple_protocols) {
188 std::string temp_value;
189 if (!headers->EnumerateHeader(
190 &state, websockets::kSecWebSocketProtocol, &temp_value))
191 break;
192 value = temp_value;
193 if (requested_set.count(value) == 0)
194 has_invalid_protocol = true;
195 if (++count > 1)
196 has_multiple_protocols = true;
[email protected]d51365e2013-11-27 10:46:52197 }
[email protected]96868202014-01-09 10:38:04198
199 if (has_multiple_protocols) {
200 *failure_message =
201 MultipleHeaderValuesMessage(websockets::kSecWebSocketProtocol);
202 return false;
203 } else if (count > 0 && requested_sub_protocols.size() == 0) {
204 *failure_message =
205 std::string("Response must not include 'Sec-WebSocket-Protocol' "
206 "header if not present in request: ")
207 + value;
208 return false;
209 } else if (has_invalid_protocol) {
210 *failure_message =
211 "'Sec-WebSocket-Protocol' header value '" +
212 value +
213 "' in response does not match any of sent values";
214 return false;
215 } else if (requested_sub_protocols.size() > 0 && count == 0) {
216 *failure_message =
217 "Sent non-empty 'Sec-WebSocket-Protocol' header "
218 "but no response was received";
219 return false;
220 }
221 *sub_protocol = value;
222 return true;
[email protected]d51365e2013-11-27 10:46:52223}
224
[email protected]0be93922014-01-29 00:42:45225bool ValidatePerMessageDeflateExtension(const WebSocketExtension& extension,
226 std::string* failure_message,
227 WebSocketExtensionParams* params) {
228 static const char kClientPrefix[] = "client_";
229 static const char kServerPrefix[] = "server_";
230 static const char kNoContextTakeover[] = "no_context_takeover";
231 static const char kMaxWindowBits[] = "max_window_bits";
232 const size_t kPrefixLen = arraysize(kClientPrefix) - 1;
233 COMPILE_ASSERT(kPrefixLen == arraysize(kServerPrefix) - 1,
234 the_strings_server_and_client_must_be_the_same_length);
235 typedef std::vector<WebSocketExtension::Parameter> ParameterVector;
236
[email protected]e5760f522014-02-05 12:28:50237 DCHECK_EQ("permessage-deflate", extension.name());
[email protected]0be93922014-01-29 00:42:45238 const ParameterVector& parameters = extension.parameters();
239 std::set<std::string> seen_names;
240 for (ParameterVector::const_iterator it = parameters.begin();
241 it != parameters.end(); ++it) {
242 const std::string& name = it->name();
243 if (seen_names.count(name) != 0) {
244 *failure_message =
245 "Received duplicate permessage-deflate extension parameter " + name;
246 return false;
247 }
248 seen_names.insert(name);
249 const std::string client_or_server(name, 0, kPrefixLen);
250 const bool is_client = (client_or_server == kClientPrefix);
251 if (!is_client && client_or_server != kServerPrefix) {
252 *failure_message =
253 "Received an unexpected permessage-deflate extension parameter";
254 return false;
255 }
256 const std::string rest(name, kPrefixLen);
257 if (rest == kNoContextTakeover) {
258 if (it->HasValue()) {
259 *failure_message = "Received invalid " + name + " parameter";
260 return false;
261 }
262 if (is_client)
263 params->deflate_mode = WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT;
264 } else if (rest == kMaxWindowBits) {
265 if (!it->HasValue()) {
266 *failure_message = name + " must have value";
267 return false;
268 }
269 int bits = 0;
270 if (!base::StringToInt(it->value(), &bits) || bits < 8 || bits > 15 ||
271 it->value()[0] == '0' ||
272 it->value().find_first_not_of("0123456789") != std::string::npos) {
273 *failure_message = "Received invalid " + name + " parameter";
274 return false;
275 }
276 if (is_client)
277 params->client_window_bits = bits;
278 } else {
279 *failure_message =
280 "Received an unexpected permessage-deflate extension parameter";
281 return false;
282 }
283 }
284 params->deflate_enabled = true;
285 return true;
286}
287
[email protected]96868202014-01-09 10:38:04288bool ValidateExtensions(const HttpResponseHeaders* headers,
[email protected]d51365e2013-11-27 10:46:52289 const std::vector<std::string>& requested_extensions,
[email protected]96868202014-01-09 10:38:04290 std::string* extensions,
[email protected]0be93922014-01-29 00:42:45291 std::string* failure_message,
292 WebSocketExtensionParams* params) {
[email protected]d51365e2013-11-27 10:46:52293 void* state = NULL;
[email protected]96868202014-01-09 10:38:04294 std::string value;
[email protected]0be93922014-01-29 00:42:45295 std::vector<std::string> accepted_extensions;
296 // TODO(ricea): If adding support for additional extensions, generalise this
297 // code.
298 bool seen_permessage_deflate = false;
[email protected]d51365e2013-11-27 10:46:52299 while (headers->EnumerateHeader(
[email protected]e5760f522014-02-05 12:28:50300 &state, websockets::kSecWebSocketExtensions, &value)) {
[email protected]96868202014-01-09 10:38:04301 WebSocketExtensionParser parser;
302 parser.Parse(value);
303 if (parser.has_error()) {
304 // TODO(yhirano) Set appropriate failure message.
305 *failure_message =
306 "'Sec-WebSocket-Extensions' header value is "
307 "rejected by the parser: " +
308 value;
309 return false;
310 }
[email protected]0be93922014-01-29 00:42:45311 if (parser.extension().name() == "permessage-deflate") {
312 if (seen_permessage_deflate) {
313 *failure_message = "Received duplicate permessage-deflate response";
314 return false;
315 }
316 seen_permessage_deflate = true;
317 if (!ValidatePerMessageDeflateExtension(
[email protected]e5760f522014-02-05 12:28:50318 parser.extension(), failure_message, params))
[email protected]0be93922014-01-29 00:42:45319 return false;
320 } else {
321 *failure_message =
322 "Found an unsupported extension '" +
323 parser.extension().name() +
324 "' in 'Sec-WebSocket-Extensions' header";
325 return false;
326 }
327 accepted_extensions.push_back(value);
[email protected]d51365e2013-11-27 10:46:52328 }
[email protected]0be93922014-01-29 00:42:45329 *extensions = JoinString(accepted_extensions, ", ");
[email protected]d51365e2013-11-27 10:46:52330 return true;
331}
332
333} // namespace
334
335WebSocketBasicHandshakeStream::WebSocketBasicHandshakeStream(
336 scoped_ptr<ClientSocketHandle> connection,
[email protected]cd48ed12014-01-22 14:34:22337 WebSocketStream::ConnectDelegate* connect_delegate,
[email protected]d51365e2013-11-27 10:46:52338 bool using_proxy,
339 std::vector<std::string> requested_sub_protocols,
340 std::vector<std::string> requested_extensions)
341 : state_(connection.release(), using_proxy),
[email protected]cd48ed12014-01-22 14:34:22342 connect_delegate_(connect_delegate),
[email protected]d51365e2013-11-27 10:46:52343 http_response_info_(NULL),
344 requested_sub_protocols_(requested_sub_protocols),
345 requested_extensions_(requested_extensions) {}
346
347WebSocketBasicHandshakeStream::~WebSocketBasicHandshakeStream() {}
348
349int WebSocketBasicHandshakeStream::InitializeStream(
350 const HttpRequestInfo* request_info,
351 RequestPriority priority,
352 const BoundNetLog& net_log,
353 const CompletionCallback& callback) {
[email protected]cd48ed12014-01-22 14:34:22354 url_ = request_info->url;
[email protected]d51365e2013-11-27 10:46:52355 state_.Initialize(request_info, priority, net_log, callback);
356 return OK;
357}
358
359int WebSocketBasicHandshakeStream::SendRequest(
360 const HttpRequestHeaders& headers,
361 HttpResponseInfo* response,
362 const CompletionCallback& callback) {
363 DCHECK(!headers.HasHeader(websockets::kSecWebSocketKey));
364 DCHECK(!headers.HasHeader(websockets::kSecWebSocketProtocol));
365 DCHECK(!headers.HasHeader(websockets::kSecWebSocketExtensions));
366 DCHECK(headers.HasHeader(HttpRequestHeaders::kOrigin));
367 DCHECK(headers.HasHeader(websockets::kUpgrade));
368 DCHECK(headers.HasHeader(HttpRequestHeaders::kConnection));
369 DCHECK(headers.HasHeader(websockets::kSecWebSocketVersion));
370 DCHECK(parser());
371
372 http_response_info_ = response;
373
374 // Create a copy of the headers object, so that we can add the
375 // Sec-WebSockey-Key header.
376 HttpRequestHeaders enriched_headers;
377 enriched_headers.CopyFrom(headers);
[email protected]a31ecc02013-12-05 08:30:55378 std::string handshake_challenge;
379 if (handshake_challenge_for_testing_) {
380 handshake_challenge = *handshake_challenge_for_testing_;
381 handshake_challenge_for_testing_.reset();
382 } else {
383 handshake_challenge = GenerateHandshakeChallenge();
384 }
[email protected]d51365e2013-11-27 10:46:52385 enriched_headers.SetHeader(websockets::kSecWebSocketKey, handshake_challenge);
386
[email protected]d51365e2013-11-27 10:46:52387 AddVectorHeaderIfNonEmpty(websockets::kSecWebSocketExtensions,
388 requested_extensions_,
389 &enriched_headers);
[email protected]0be93922014-01-29 00:42:45390 AddVectorHeaderIfNonEmpty(websockets::kSecWebSocketProtocol,
391 requested_sub_protocols_,
392 &enriched_headers);
[email protected]d51365e2013-11-27 10:46:52393
394 ComputeSecWebSocketAccept(handshake_challenge,
395 &handshake_challenge_response_);
396
[email protected]cd48ed12014-01-22 14:34:22397 DCHECK(connect_delegate_);
398 scoped_ptr<WebSocketHandshakeRequestInfo> request(
399 new WebSocketHandshakeRequestInfo(url_, base::Time::Now()));
400 request->headers.CopyFrom(enriched_headers);
401 connect_delegate_->OnStartOpeningHandshake(request.Pass());
402
[email protected]d51365e2013-11-27 10:46:52403 return parser()->SendRequest(
404 state_.GenerateRequestLine(), enriched_headers, response, callback);
405}
406
407int WebSocketBasicHandshakeStream::ReadResponseHeaders(
408 const CompletionCallback& callback) {
409 // HttpStreamParser uses a weak pointer when reading from the
410 // socket, so it won't be called back after being destroyed. The
411 // HttpStreamParser is owned by HttpBasicState which is owned by this object,
412 // so this use of base::Unretained() is safe.
413 int rv = parser()->ReadResponseHeaders(
414 base::Bind(&WebSocketBasicHandshakeStream::ReadResponseHeadersCallback,
415 base::Unretained(this),
416 callback));
[email protected]cd48ed12014-01-22 14:34:22417 if (rv == ERR_IO_PENDING)
418 return rv;
[email protected]e5760f522014-02-05 12:28:50419 return ValidateResponse(rv);
[email protected]d51365e2013-11-27 10:46:52420}
421
422const HttpResponseInfo* WebSocketBasicHandshakeStream::GetResponseInfo() const {
423 return parser()->GetResponseInfo();
424}
425
426int WebSocketBasicHandshakeStream::ReadResponseBody(
427 IOBuffer* buf,
428 int buf_len,
429 const CompletionCallback& callback) {
430 return parser()->ReadResponseBody(buf, buf_len, callback);
431}
432
433void WebSocketBasicHandshakeStream::Close(bool not_reusable) {
434 // This class ignores the value of |not_reusable| and never lets the socket be
435 // re-used.
436 if (parser())
437 parser()->Close(true);
438}
439
440bool WebSocketBasicHandshakeStream::IsResponseBodyComplete() const {
441 return parser()->IsResponseBodyComplete();
442}
443
444bool WebSocketBasicHandshakeStream::CanFindEndOfResponse() const {
445 return parser() && parser()->CanFindEndOfResponse();
446}
447
448bool WebSocketBasicHandshakeStream::IsConnectionReused() const {
449 return parser()->IsConnectionReused();
450}
451
452void WebSocketBasicHandshakeStream::SetConnectionReused() {
453 parser()->SetConnectionReused();
454}
455
456bool WebSocketBasicHandshakeStream::IsConnectionReusable() const {
457 return false;
458}
459
[email protected]bc92bc972013-12-13 08:32:59460int64 WebSocketBasicHandshakeStream::GetTotalReceivedBytes() const {
461 return 0;
462}
463
[email protected]d51365e2013-11-27 10:46:52464bool WebSocketBasicHandshakeStream::GetLoadTimingInfo(
465 LoadTimingInfo* load_timing_info) const {
466 return state_.connection()->GetLoadTimingInfo(IsConnectionReused(),
467 load_timing_info);
468}
469
470void WebSocketBasicHandshakeStream::GetSSLInfo(SSLInfo* ssl_info) {
471 parser()->GetSSLInfo(ssl_info);
472}
473
474void WebSocketBasicHandshakeStream::GetSSLCertRequestInfo(
475 SSLCertRequestInfo* cert_request_info) {
476 parser()->GetSSLCertRequestInfo(cert_request_info);
477}
478
479bool WebSocketBasicHandshakeStream::IsSpdyHttpStream() const { return false; }
480
481void WebSocketBasicHandshakeStream::Drain(HttpNetworkSession* session) {
482 HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
483 drainer->Start(session);
484 // |drainer| will delete itself.
485}
486
487void WebSocketBasicHandshakeStream::SetPriority(RequestPriority priority) {
488 // TODO(ricea): See TODO comment in HttpBasicStream::SetPriority(). If it is
489 // gone, then copy whatever has happened there over here.
490}
491
492scoped_ptr<WebSocketStream> WebSocketBasicHandshakeStream::Upgrade() {
[email protected]d51365e2013-11-27 10:46:52493 // The HttpStreamParser object has a pointer to our ClientSocketHandle. Make
494 // sure it does not touch it again before it is destroyed.
495 state_.DeleteParser();
[email protected]0be93922014-01-29 00:42:45496 scoped_ptr<WebSocketStream> basic_stream(
[email protected]d51365e2013-11-27 10:46:52497 new WebSocketBasicStream(state_.ReleaseConnection(),
498 state_.read_buf(),
499 sub_protocol_,
500 extensions_));
[email protected]0be93922014-01-29 00:42:45501 DCHECK(extension_params_.get());
502 if (extension_params_->deflate_enabled) {
503 return scoped_ptr<WebSocketStream>(
504 new WebSocketDeflateStream(basic_stream.Pass(),
505 extension_params_->deflate_mode,
506 extension_params_->client_window_bits,
507 scoped_ptr<WebSocketDeflatePredictor>(
508 new WebSocketDeflatePredictorImpl)));
509 } else {
510 return basic_stream.Pass();
511 }
[email protected]d51365e2013-11-27 10:46:52512}
513
[email protected]a31ecc02013-12-05 08:30:55514void WebSocketBasicHandshakeStream::SetWebSocketKeyForTesting(
515 const std::string& key) {
516 handshake_challenge_for_testing_.reset(new std::string(key));
517}
518
[email protected]96868202014-01-09 10:38:04519std::string WebSocketBasicHandshakeStream::GetFailureMessage() const {
520 return failure_message_;
521}
522
[email protected]d51365e2013-11-27 10:46:52523void WebSocketBasicHandshakeStream::ReadResponseHeadersCallback(
524 const CompletionCallback& callback,
525 int result) {
[email protected]e5760f522014-02-05 12:28:50526 callback.Run(ValidateResponse(result));
[email protected]d51365e2013-11-27 10:46:52527}
528
[email protected]cd48ed12014-01-22 14:34:22529void WebSocketBasicHandshakeStream::OnFinishOpeningHandshake() {
530 DCHECK(connect_delegate_);
531 DCHECK(http_response_info_);
532 scoped_refptr<HttpResponseHeaders> headers = http_response_info_->headers;
[email protected]94831522014-02-06 12:05:18533 // If the headers are too large, HttpStreamParser will just not parse them at
534 // all.
535 if (headers) {
536 scoped_ptr<WebSocketHandshakeResponseInfo> response(
537 new WebSocketHandshakeResponseInfo(url_,
538 headers->response_code(),
539 headers->GetStatusText(),
540 headers,
541 http_response_info_->response_time));
542 connect_delegate_->OnFinishOpeningHandshake(response.Pass());
543 }
[email protected]cd48ed12014-01-22 14:34:22544}
545
[email protected]e5760f522014-02-05 12:28:50546int WebSocketBasicHandshakeStream::ValidateResponse(int rv) {
[email protected]d51365e2013-11-27 10:46:52547 DCHECK(http_response_info_);
[email protected]e5760f522014-02-05 12:28:50548 const HttpResponseHeaders* headers = http_response_info_->headers.get();
549 if (rv >= 0) {
550 switch (headers->response_code()) {
551 case HTTP_SWITCHING_PROTOCOLS:
552 OnFinishOpeningHandshake();
553 return ValidateUpgradeResponse(headers);
[email protected]d51365e2013-11-27 10:46:52554
[email protected]e5760f522014-02-05 12:28:50555 // We need to pass these through for authentication to work.
556 case HTTP_UNAUTHORIZED:
557 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
558 return OK;
[email protected]d51365e2013-11-27 10:46:52559
[email protected]e5760f522014-02-05 12:28:50560 // Other status codes are potentially risky (see the warnings in the
561 // WHATWG WebSocket API spec) and so are dropped by default.
562 default:
563 failure_message_ = base::StringPrintf(
564 "Error during WebSocket handshake: Unexpected response code: %d",
565 headers->response_code());
566 OnFinishOpeningHandshake();
567 return ERR_INVALID_RESPONSE;
568 }
569 } else {
[email protected]3efc08f2014-02-07 09:33:34570 if (rv == ERR_EMPTY_RESPONSE) {
571 failure_message_ =
572 "Connection closed before receiving a handshake response";
573 return rv;
574 }
[email protected]e5760f522014-02-05 12:28:50575 failure_message_ =
576 std::string("Error during WebSocket handshake: ") + ErrorToString(rv);
577 OnFinishOpeningHandshake();
578 return rv;
[email protected]d51365e2013-11-27 10:46:52579 }
580}
581
582int WebSocketBasicHandshakeStream::ValidateUpgradeResponse(
[email protected]e5760f522014-02-05 12:28:50583 const HttpResponseHeaders* headers) {
[email protected]0be93922014-01-29 00:42:45584 extension_params_.reset(new WebSocketExtensionParams);
[email protected]e5760f522014-02-05 12:28:50585 if (ValidateUpgrade(headers, &failure_message_) &&
586 ValidateSecWebSocketAccept(headers,
[email protected]96868202014-01-09 10:38:04587 handshake_challenge_response_,
588 &failure_message_) &&
[email protected]e5760f522014-02-05 12:28:50589 ValidateConnection(headers, &failure_message_) &&
590 ValidateSubProtocol(headers,
[email protected]96868202014-01-09 10:38:04591 requested_sub_protocols_,
592 &sub_protocol_,
593 &failure_message_) &&
[email protected]e5760f522014-02-05 12:28:50594 ValidateExtensions(headers,
[email protected]96868202014-01-09 10:38:04595 requested_extensions_,
596 &extensions_,
[email protected]0be93922014-01-29 00:42:45597 &failure_message_,
598 extension_params_.get())) {
[email protected]d51365e2013-11-27 10:46:52599 return OK;
600 }
[email protected]96868202014-01-09 10:38:04601 failure_message_ = "Error during WebSocket handshake: " + failure_message_;
[email protected]d51365e2013-11-27 10:46:52602 return ERR_INVALID_RESPONSE;
603}
604
605} // namespace net