blob: 6d769e0d35ab9f4b43c1e58e77deffa681e84375 [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]69d7a492014-02-19 08:36:3219#include "base/strings/string_piece.h"
[email protected]d51365e2013-11-27 10:46:5220#include "base/strings/string_util.h"
[email protected]96868202014-01-09 10:38:0421#include "base/strings/stringprintf.h"
[email protected]cd48ed12014-01-22 14:34:2222#include "base/time/time.h"
[email protected]d51365e2013-11-27 10:46:5223#include "crypto/random.h"
24#include "net/http/http_request_headers.h"
25#include "net/http/http_request_info.h"
26#include "net/http/http_response_body_drainer.h"
27#include "net/http/http_response_headers.h"
28#include "net/http/http_status_code.h"
29#include "net/http/http_stream_parser.h"
30#include "net/socket/client_socket_handle.h"
31#include "net/websockets/websocket_basic_stream.h"
[email protected]0be93922014-01-29 00:42:4532#include "net/websockets/websocket_deflate_predictor.h"
33#include "net/websockets/websocket_deflate_predictor_impl.h"
34#include "net/websockets/websocket_deflate_stream.h"
35#include "net/websockets/websocket_deflater.h"
[email protected]96868202014-01-09 10:38:0436#include "net/websockets/websocket_extension_parser.h"
[email protected]d51365e2013-11-27 10:46:5237#include "net/websockets/websocket_handshake_constants.h"
38#include "net/websockets/websocket_handshake_handler.h"
[email protected]cd48ed12014-01-22 14:34:2239#include "net/websockets/websocket_handshake_request_info.h"
40#include "net/websockets/websocket_handshake_response_info.h"
[email protected]d51365e2013-11-27 10:46:5241#include "net/websockets/websocket_stream.h"
42
43namespace net {
[email protected]0be93922014-01-29 00:42:4544
45// TODO(ricea): If more extensions are added, replace this with a more general
46// mechanism.
47struct WebSocketExtensionParams {
48 WebSocketExtensionParams()
49 : deflate_enabled(false),
50 client_window_bits(15),
51 deflate_mode(WebSocketDeflater::TAKE_OVER_CONTEXT) {}
52
53 bool deflate_enabled;
54 int client_window_bits;
55 WebSocketDeflater::ContextTakeOverMode deflate_mode;
56};
57
[email protected]d51365e2013-11-27 10:46:5258namespace {
59
[email protected]96868202014-01-09 10:38:0460enum GetHeaderResult {
61 GET_HEADER_OK,
62 GET_HEADER_MISSING,
63 GET_HEADER_MULTIPLE,
64};
65
66std::string MissingHeaderMessage(const std::string& header_name) {
67 return std::string("'") + header_name + "' header is missing";
68}
69
70std::string MultipleHeaderValuesMessage(const std::string& header_name) {
71 return
72 std::string("'") +
73 header_name +
74 "' header must not appear more than once in a response";
75}
76
[email protected]d51365e2013-11-27 10:46:5277std::string GenerateHandshakeChallenge() {
78 std::string raw_challenge(websockets::kRawChallengeLength, '\0');
79 crypto::RandBytes(string_as_array(&raw_challenge), raw_challenge.length());
80 std::string encoded_challenge;
[email protected]33fca122013-12-11 01:48:5081 base::Base64Encode(raw_challenge, &encoded_challenge);
[email protected]d51365e2013-11-27 10:46:5282 return encoded_challenge;
83}
84
85void AddVectorHeaderIfNonEmpty(const char* name,
86 const std::vector<std::string>& value,
87 HttpRequestHeaders* headers) {
88 if (value.empty())
89 return;
90 headers->SetHeader(name, JoinString(value, ", "));
91}
92
[email protected]96868202014-01-09 10:38:0493GetHeaderResult GetSingleHeaderValue(const HttpResponseHeaders* headers,
94 const base::StringPiece& name,
95 std::string* value) {
[email protected]d51365e2013-11-27 10:46:5296 void* state = NULL;
[email protected]96868202014-01-09 10:38:0497 size_t num_values = 0;
98 std::string temp_value;
99 while (headers->EnumerateHeader(&state, name, &temp_value)) {
100 if (++num_values > 1)
101 return GET_HEADER_MULTIPLE;
102 *value = temp_value;
[email protected]d51365e2013-11-27 10:46:52103 }
[email protected]96868202014-01-09 10:38:04104 return num_values > 0 ? GET_HEADER_OK : GET_HEADER_MISSING;
105}
106
107bool ValidateHeaderHasSingleValue(GetHeaderResult result,
108 const std::string& header_name,
109 std::string* failure_message) {
110 if (result == GET_HEADER_MISSING) {
111 *failure_message = MissingHeaderMessage(header_name);
112 return false;
113 }
114 if (result == GET_HEADER_MULTIPLE) {
115 *failure_message = MultipleHeaderValuesMessage(header_name);
116 return false;
117 }
118 DCHECK_EQ(result, GET_HEADER_OK);
119 return true;
120}
121
122bool ValidateUpgrade(const HttpResponseHeaders* headers,
123 std::string* failure_message) {
124 std::string value;
125 GetHeaderResult result =
126 GetSingleHeaderValue(headers, websockets::kUpgrade, &value);
127 if (!ValidateHeaderHasSingleValue(result,
128 websockets::kUpgrade,
129 failure_message)) {
130 return false;
131 }
132
133 if (!LowerCaseEqualsASCII(value, websockets::kWebSocketLowercase)) {
134 *failure_message =
135 "'Upgrade' header value is not 'WebSocket': " + value;
136 return false;
137 }
138 return true;
139}
140
141bool ValidateSecWebSocketAccept(const HttpResponseHeaders* headers,
142 const std::string& expected,
143 std::string* failure_message) {
144 std::string actual;
145 GetHeaderResult result =
146 GetSingleHeaderValue(headers, websockets::kSecWebSocketAccept, &actual);
147 if (!ValidateHeaderHasSingleValue(result,
148 websockets::kSecWebSocketAccept,
149 failure_message)) {
150 return false;
151 }
152
153 if (expected != actual) {
154 *failure_message = "Incorrect 'Sec-WebSocket-Accept' header value";
155 return false;
156 }
157 return true;
158}
159
160bool ValidateConnection(const HttpResponseHeaders* headers,
161 std::string* failure_message) {
162 // Connection header is permitted to contain other tokens.
163 if (!headers->HasHeader(HttpRequestHeaders::kConnection)) {
164 *failure_message = MissingHeaderMessage(HttpRequestHeaders::kConnection);
165 return false;
166 }
167 if (!headers->HasHeaderValue(HttpRequestHeaders::kConnection,
168 websockets::kUpgrade)) {
169 *failure_message = "'Connection' header value must contain 'Upgrade'";
170 return false;
171 }
172 return true;
[email protected]d51365e2013-11-27 10:46:52173}
174
175bool ValidateSubProtocol(
[email protected]96868202014-01-09 10:38:04176 const HttpResponseHeaders* headers,
[email protected]d51365e2013-11-27 10:46:52177 const std::vector<std::string>& requested_sub_protocols,
[email protected]96868202014-01-09 10:38:04178 std::string* sub_protocol,
179 std::string* failure_message) {
[email protected]d51365e2013-11-27 10:46:52180 void* state = NULL;
[email protected]96868202014-01-09 10:38:04181 std::string value;
[email protected]d51365e2013-11-27 10:46:52182 base::hash_set<std::string> requested_set(requested_sub_protocols.begin(),
183 requested_sub_protocols.end());
[email protected]96868202014-01-09 10:38:04184 int count = 0;
185 bool has_multiple_protocols = false;
186 bool has_invalid_protocol = false;
[email protected]d51365e2013-11-27 10:46:52187
[email protected]96868202014-01-09 10:38:04188 while (!has_invalid_protocol || !has_multiple_protocols) {
189 std::string temp_value;
190 if (!headers->EnumerateHeader(
191 &state, websockets::kSecWebSocketProtocol, &temp_value))
192 break;
193 value = temp_value;
194 if (requested_set.count(value) == 0)
195 has_invalid_protocol = true;
196 if (++count > 1)
197 has_multiple_protocols = true;
[email protected]d51365e2013-11-27 10:46:52198 }
[email protected]96868202014-01-09 10:38:04199
200 if (has_multiple_protocols) {
201 *failure_message =
202 MultipleHeaderValuesMessage(websockets::kSecWebSocketProtocol);
203 return false;
204 } else if (count > 0 && requested_sub_protocols.size() == 0) {
205 *failure_message =
206 std::string("Response must not include 'Sec-WebSocket-Protocol' "
207 "header if not present in request: ")
208 + value;
209 return false;
210 } else if (has_invalid_protocol) {
211 *failure_message =
212 "'Sec-WebSocket-Protocol' header value '" +
213 value +
214 "' in response does not match any of sent values";
215 return false;
216 } else if (requested_sub_protocols.size() > 0 && count == 0) {
217 *failure_message =
218 "Sent non-empty 'Sec-WebSocket-Protocol' header "
219 "but no response was received";
220 return false;
221 }
222 *sub_protocol = value;
223 return true;
[email protected]d51365e2013-11-27 10:46:52224}
225
[email protected]69d7a492014-02-19 08:36:32226bool DeflateError(std::string* message, const base::StringPiece& piece) {
227 *message = "Error in permessage-deflate: ";
228 AppendToString(piece, message);
229 return false;
230}
231
[email protected]0be93922014-01-29 00:42:45232bool ValidatePerMessageDeflateExtension(const WebSocketExtension& extension,
233 std::string* failure_message,
234 WebSocketExtensionParams* params) {
235 static const char kClientPrefix[] = "client_";
236 static const char kServerPrefix[] = "server_";
237 static const char kNoContextTakeover[] = "no_context_takeover";
238 static const char kMaxWindowBits[] = "max_window_bits";
239 const size_t kPrefixLen = arraysize(kClientPrefix) - 1;
240 COMPILE_ASSERT(kPrefixLen == arraysize(kServerPrefix) - 1,
241 the_strings_server_and_client_must_be_the_same_length);
242 typedef std::vector<WebSocketExtension::Parameter> ParameterVector;
243
[email protected]e5760f522014-02-05 12:28:50244 DCHECK_EQ("permessage-deflate", extension.name());
[email protected]0be93922014-01-29 00:42:45245 const ParameterVector& parameters = extension.parameters();
246 std::set<std::string> seen_names;
247 for (ParameterVector::const_iterator it = parameters.begin();
248 it != parameters.end(); ++it) {
249 const std::string& name = it->name();
250 if (seen_names.count(name) != 0) {
[email protected]69d7a492014-02-19 08:36:32251 return DeflateError(
252 failure_message,
253 "Received duplicate permessage-deflate extension parameter " + name);
[email protected]0be93922014-01-29 00:42:45254 }
255 seen_names.insert(name);
256 const std::string client_or_server(name, 0, kPrefixLen);
257 const bool is_client = (client_or_server == kClientPrefix);
258 if (!is_client && client_or_server != kServerPrefix) {
[email protected]69d7a492014-02-19 08:36:32259 return DeflateError(
260 failure_message,
261 "Received an unexpected permessage-deflate extension parameter");
[email protected]0be93922014-01-29 00:42:45262 }
263 const std::string rest(name, kPrefixLen);
264 if (rest == kNoContextTakeover) {
265 if (it->HasValue()) {
[email protected]69d7a492014-02-19 08:36:32266 return DeflateError(failure_message,
267 "Received invalid " + name + " parameter");
[email protected]0be93922014-01-29 00:42:45268 }
269 if (is_client)
270 params->deflate_mode = WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT;
271 } else if (rest == kMaxWindowBits) {
[email protected]69d7a492014-02-19 08:36:32272 if (!it->HasValue())
273 return DeflateError(failure_message, name + " must have value");
[email protected]0be93922014-01-29 00:42:45274 int bits = 0;
275 if (!base::StringToInt(it->value(), &bits) || bits < 8 || bits > 15 ||
276 it->value()[0] == '0' ||
277 it->value().find_first_not_of("0123456789") != std::string::npos) {
[email protected]69d7a492014-02-19 08:36:32278 return DeflateError(failure_message,
279 "Received invalid " + name + " parameter");
[email protected]0be93922014-01-29 00:42:45280 }
281 if (is_client)
282 params->client_window_bits = bits;
283 } else {
[email protected]69d7a492014-02-19 08:36:32284 return DeflateError(
285 failure_message,
286 "Received an unexpected permessage-deflate extension parameter");
[email protected]0be93922014-01-29 00:42:45287 }
288 }
289 params->deflate_enabled = true;
290 return true;
291}
292
[email protected]96868202014-01-09 10:38:04293bool ValidateExtensions(const HttpResponseHeaders* headers,
[email protected]d51365e2013-11-27 10:46:52294 const std::vector<std::string>& requested_extensions,
[email protected]96868202014-01-09 10:38:04295 std::string* extensions,
[email protected]0be93922014-01-29 00:42:45296 std::string* failure_message,
297 WebSocketExtensionParams* params) {
[email protected]d51365e2013-11-27 10:46:52298 void* state = NULL;
[email protected]96868202014-01-09 10:38:04299 std::string value;
[email protected]0be93922014-01-29 00:42:45300 std::vector<std::string> accepted_extensions;
301 // TODO(ricea): If adding support for additional extensions, generalise this
302 // code.
303 bool seen_permessage_deflate = false;
[email protected]d51365e2013-11-27 10:46:52304 while (headers->EnumerateHeader(
[email protected]e5760f522014-02-05 12:28:50305 &state, websockets::kSecWebSocketExtensions, &value)) {
[email protected]96868202014-01-09 10:38:04306 WebSocketExtensionParser parser;
307 parser.Parse(value);
308 if (parser.has_error()) {
309 // TODO(yhirano) Set appropriate failure message.
310 *failure_message =
311 "'Sec-WebSocket-Extensions' header value is "
312 "rejected by the parser: " +
313 value;
314 return false;
315 }
[email protected]0be93922014-01-29 00:42:45316 if (parser.extension().name() == "permessage-deflate") {
317 if (seen_permessage_deflate) {
318 *failure_message = "Received duplicate permessage-deflate response";
319 return false;
320 }
321 seen_permessage_deflate = true;
322 if (!ValidatePerMessageDeflateExtension(
[email protected]e5760f522014-02-05 12:28:50323 parser.extension(), failure_message, params))
[email protected]0be93922014-01-29 00:42:45324 return false;
325 } else {
326 *failure_message =
327 "Found an unsupported extension '" +
328 parser.extension().name() +
329 "' in 'Sec-WebSocket-Extensions' header";
330 return false;
331 }
332 accepted_extensions.push_back(value);
[email protected]d51365e2013-11-27 10:46:52333 }
[email protected]0be93922014-01-29 00:42:45334 *extensions = JoinString(accepted_extensions, ", ");
[email protected]d51365e2013-11-27 10:46:52335 return true;
336}
337
338} // namespace
339
340WebSocketBasicHandshakeStream::WebSocketBasicHandshakeStream(
341 scoped_ptr<ClientSocketHandle> connection,
[email protected]cd48ed12014-01-22 14:34:22342 WebSocketStream::ConnectDelegate* connect_delegate,
[email protected]d51365e2013-11-27 10:46:52343 bool using_proxy,
344 std::vector<std::string> requested_sub_protocols,
345 std::vector<std::string> requested_extensions)
346 : state_(connection.release(), using_proxy),
[email protected]cd48ed12014-01-22 14:34:22347 connect_delegate_(connect_delegate),
[email protected]d51365e2013-11-27 10:46:52348 http_response_info_(NULL),
349 requested_sub_protocols_(requested_sub_protocols),
350 requested_extensions_(requested_extensions) {}
351
352WebSocketBasicHandshakeStream::~WebSocketBasicHandshakeStream() {}
353
354int WebSocketBasicHandshakeStream::InitializeStream(
355 const HttpRequestInfo* request_info,
356 RequestPriority priority,
357 const BoundNetLog& net_log,
358 const CompletionCallback& callback) {
[email protected]cd48ed12014-01-22 14:34:22359 url_ = request_info->url;
[email protected]d51365e2013-11-27 10:46:52360 state_.Initialize(request_info, priority, net_log, callback);
361 return OK;
362}
363
364int WebSocketBasicHandshakeStream::SendRequest(
365 const HttpRequestHeaders& headers,
366 HttpResponseInfo* response,
367 const CompletionCallback& callback) {
368 DCHECK(!headers.HasHeader(websockets::kSecWebSocketKey));
369 DCHECK(!headers.HasHeader(websockets::kSecWebSocketProtocol));
370 DCHECK(!headers.HasHeader(websockets::kSecWebSocketExtensions));
371 DCHECK(headers.HasHeader(HttpRequestHeaders::kOrigin));
372 DCHECK(headers.HasHeader(websockets::kUpgrade));
373 DCHECK(headers.HasHeader(HttpRequestHeaders::kConnection));
374 DCHECK(headers.HasHeader(websockets::kSecWebSocketVersion));
375 DCHECK(parser());
376
377 http_response_info_ = response;
378
379 // Create a copy of the headers object, so that we can add the
380 // Sec-WebSockey-Key header.
381 HttpRequestHeaders enriched_headers;
382 enriched_headers.CopyFrom(headers);
[email protected]a31ecc02013-12-05 08:30:55383 std::string handshake_challenge;
384 if (handshake_challenge_for_testing_) {
385 handshake_challenge = *handshake_challenge_for_testing_;
386 handshake_challenge_for_testing_.reset();
387 } else {
388 handshake_challenge = GenerateHandshakeChallenge();
389 }
[email protected]d51365e2013-11-27 10:46:52390 enriched_headers.SetHeader(websockets::kSecWebSocketKey, handshake_challenge);
391
[email protected]d51365e2013-11-27 10:46:52392 AddVectorHeaderIfNonEmpty(websockets::kSecWebSocketExtensions,
393 requested_extensions_,
394 &enriched_headers);
[email protected]0be93922014-01-29 00:42:45395 AddVectorHeaderIfNonEmpty(websockets::kSecWebSocketProtocol,
396 requested_sub_protocols_,
397 &enriched_headers);
[email protected]d51365e2013-11-27 10:46:52398
399 ComputeSecWebSocketAccept(handshake_challenge,
400 &handshake_challenge_response_);
401
[email protected]cd48ed12014-01-22 14:34:22402 DCHECK(connect_delegate_);
403 scoped_ptr<WebSocketHandshakeRequestInfo> request(
404 new WebSocketHandshakeRequestInfo(url_, base::Time::Now()));
405 request->headers.CopyFrom(enriched_headers);
406 connect_delegate_->OnStartOpeningHandshake(request.Pass());
407
[email protected]d51365e2013-11-27 10:46:52408 return parser()->SendRequest(
409 state_.GenerateRequestLine(), enriched_headers, response, callback);
410}
411
412int WebSocketBasicHandshakeStream::ReadResponseHeaders(
413 const CompletionCallback& callback) {
414 // HttpStreamParser uses a weak pointer when reading from the
415 // socket, so it won't be called back after being destroyed. The
416 // HttpStreamParser is owned by HttpBasicState which is owned by this object,
417 // so this use of base::Unretained() is safe.
418 int rv = parser()->ReadResponseHeaders(
419 base::Bind(&WebSocketBasicHandshakeStream::ReadResponseHeadersCallback,
420 base::Unretained(this),
421 callback));
[email protected]cd48ed12014-01-22 14:34:22422 if (rv == ERR_IO_PENDING)
423 return rv;
[email protected]e5760f522014-02-05 12:28:50424 return ValidateResponse(rv);
[email protected]d51365e2013-11-27 10:46:52425}
426
427const HttpResponseInfo* WebSocketBasicHandshakeStream::GetResponseInfo() const {
428 return parser()->GetResponseInfo();
429}
430
431int WebSocketBasicHandshakeStream::ReadResponseBody(
432 IOBuffer* buf,
433 int buf_len,
434 const CompletionCallback& callback) {
435 return parser()->ReadResponseBody(buf, buf_len, callback);
436}
437
438void WebSocketBasicHandshakeStream::Close(bool not_reusable) {
439 // This class ignores the value of |not_reusable| and never lets the socket be
440 // re-used.
441 if (parser())
442 parser()->Close(true);
443}
444
445bool WebSocketBasicHandshakeStream::IsResponseBodyComplete() const {
446 return parser()->IsResponseBodyComplete();
447}
448
449bool WebSocketBasicHandshakeStream::CanFindEndOfResponse() const {
450 return parser() && parser()->CanFindEndOfResponse();
451}
452
453bool WebSocketBasicHandshakeStream::IsConnectionReused() const {
454 return parser()->IsConnectionReused();
455}
456
457void WebSocketBasicHandshakeStream::SetConnectionReused() {
458 parser()->SetConnectionReused();
459}
460
461bool WebSocketBasicHandshakeStream::IsConnectionReusable() const {
462 return false;
463}
464
[email protected]bc92bc972013-12-13 08:32:59465int64 WebSocketBasicHandshakeStream::GetTotalReceivedBytes() const {
466 return 0;
467}
468
[email protected]d51365e2013-11-27 10:46:52469bool WebSocketBasicHandshakeStream::GetLoadTimingInfo(
470 LoadTimingInfo* load_timing_info) const {
471 return state_.connection()->GetLoadTimingInfo(IsConnectionReused(),
472 load_timing_info);
473}
474
475void WebSocketBasicHandshakeStream::GetSSLInfo(SSLInfo* ssl_info) {
476 parser()->GetSSLInfo(ssl_info);
477}
478
479void WebSocketBasicHandshakeStream::GetSSLCertRequestInfo(
480 SSLCertRequestInfo* cert_request_info) {
481 parser()->GetSSLCertRequestInfo(cert_request_info);
482}
483
484bool WebSocketBasicHandshakeStream::IsSpdyHttpStream() const { return false; }
485
486void WebSocketBasicHandshakeStream::Drain(HttpNetworkSession* session) {
487 HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
488 drainer->Start(session);
489 // |drainer| will delete itself.
490}
491
492void WebSocketBasicHandshakeStream::SetPriority(RequestPriority priority) {
493 // TODO(ricea): See TODO comment in HttpBasicStream::SetPriority(). If it is
494 // gone, then copy whatever has happened there over here.
495}
496
497scoped_ptr<WebSocketStream> WebSocketBasicHandshakeStream::Upgrade() {
[email protected]d51365e2013-11-27 10:46:52498 // The HttpStreamParser object has a pointer to our ClientSocketHandle. Make
499 // sure it does not touch it again before it is destroyed.
500 state_.DeleteParser();
[email protected]0be93922014-01-29 00:42:45501 scoped_ptr<WebSocketStream> basic_stream(
[email protected]d51365e2013-11-27 10:46:52502 new WebSocketBasicStream(state_.ReleaseConnection(),
503 state_.read_buf(),
504 sub_protocol_,
505 extensions_));
[email protected]0be93922014-01-29 00:42:45506 DCHECK(extension_params_.get());
507 if (extension_params_->deflate_enabled) {
508 return scoped_ptr<WebSocketStream>(
509 new WebSocketDeflateStream(basic_stream.Pass(),
510 extension_params_->deflate_mode,
511 extension_params_->client_window_bits,
512 scoped_ptr<WebSocketDeflatePredictor>(
513 new WebSocketDeflatePredictorImpl)));
514 } else {
515 return basic_stream.Pass();
516 }
[email protected]d51365e2013-11-27 10:46:52517}
518
[email protected]a31ecc02013-12-05 08:30:55519void WebSocketBasicHandshakeStream::SetWebSocketKeyForTesting(
520 const std::string& key) {
521 handshake_challenge_for_testing_.reset(new std::string(key));
522}
523
[email protected]96868202014-01-09 10:38:04524std::string WebSocketBasicHandshakeStream::GetFailureMessage() const {
525 return failure_message_;
526}
527
[email protected]d51365e2013-11-27 10:46:52528void WebSocketBasicHandshakeStream::ReadResponseHeadersCallback(
529 const CompletionCallback& callback,
530 int result) {
[email protected]e5760f522014-02-05 12:28:50531 callback.Run(ValidateResponse(result));
[email protected]d51365e2013-11-27 10:46:52532}
533
[email protected]cd48ed12014-01-22 14:34:22534void WebSocketBasicHandshakeStream::OnFinishOpeningHandshake() {
535 DCHECK(connect_delegate_);
536 DCHECK(http_response_info_);
537 scoped_refptr<HttpResponseHeaders> headers = http_response_info_->headers;
[email protected]94831522014-02-06 12:05:18538 // If the headers are too large, HttpStreamParser will just not parse them at
539 // all.
540 if (headers) {
541 scoped_ptr<WebSocketHandshakeResponseInfo> response(
542 new WebSocketHandshakeResponseInfo(url_,
543 headers->response_code(),
544 headers->GetStatusText(),
545 headers,
546 http_response_info_->response_time));
547 connect_delegate_->OnFinishOpeningHandshake(response.Pass());
548 }
[email protected]cd48ed12014-01-22 14:34:22549}
550
[email protected]e5760f522014-02-05 12:28:50551int WebSocketBasicHandshakeStream::ValidateResponse(int rv) {
[email protected]d51365e2013-11-27 10:46:52552 DCHECK(http_response_info_);
[email protected]e5760f522014-02-05 12:28:50553 const HttpResponseHeaders* headers = http_response_info_->headers.get();
554 if (rv >= 0) {
555 switch (headers->response_code()) {
556 case HTTP_SWITCHING_PROTOCOLS:
557 OnFinishOpeningHandshake();
558 return ValidateUpgradeResponse(headers);
[email protected]d51365e2013-11-27 10:46:52559
[email protected]e5760f522014-02-05 12:28:50560 // We need to pass these through for authentication to work.
561 case HTTP_UNAUTHORIZED:
562 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
563 return OK;
[email protected]d51365e2013-11-27 10:46:52564
[email protected]e5760f522014-02-05 12:28:50565 // Other status codes are potentially risky (see the warnings in the
566 // WHATWG WebSocket API spec) and so are dropped by default.
567 default:
568 failure_message_ = base::StringPrintf(
569 "Error during WebSocket handshake: Unexpected response code: %d",
570 headers->response_code());
571 OnFinishOpeningHandshake();
572 return ERR_INVALID_RESPONSE;
573 }
574 } else {
[email protected]3efc08f2014-02-07 09:33:34575 if (rv == ERR_EMPTY_RESPONSE) {
576 failure_message_ =
577 "Connection closed before receiving a handshake response";
578 return rv;
579 }
[email protected]e5760f522014-02-05 12:28:50580 failure_message_ =
581 std::string("Error during WebSocket handshake: ") + ErrorToString(rv);
582 OnFinishOpeningHandshake();
583 return rv;
[email protected]d51365e2013-11-27 10:46:52584 }
585}
586
587int WebSocketBasicHandshakeStream::ValidateUpgradeResponse(
[email protected]e5760f522014-02-05 12:28:50588 const HttpResponseHeaders* headers) {
[email protected]0be93922014-01-29 00:42:45589 extension_params_.reset(new WebSocketExtensionParams);
[email protected]e5760f522014-02-05 12:28:50590 if (ValidateUpgrade(headers, &failure_message_) &&
591 ValidateSecWebSocketAccept(headers,
[email protected]96868202014-01-09 10:38:04592 handshake_challenge_response_,
593 &failure_message_) &&
[email protected]e5760f522014-02-05 12:28:50594 ValidateConnection(headers, &failure_message_) &&
595 ValidateSubProtocol(headers,
[email protected]96868202014-01-09 10:38:04596 requested_sub_protocols_,
597 &sub_protocol_,
598 &failure_message_) &&
[email protected]e5760f522014-02-05 12:28:50599 ValidateExtensions(headers,
[email protected]96868202014-01-09 10:38:04600 requested_extensions_,
601 &extensions_,
[email protected]0be93922014-01-29 00:42:45602 &failure_message_,
603 extension_params_.get())) {
[email protected]d51365e2013-11-27 10:46:52604 return OK;
605 }
[email protected]96868202014-01-09 10:38:04606 failure_message_ = "Error during WebSocket handshake: " + failure_message_;
[email protected]d51365e2013-11-27 10:46:52607 return ERR_INVALID_RESPONSE;
608}
609
610} // namespace net