OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/websockets/websocket_basic_handshake_stream.h" | 5 #include "net/websockets/websocket_basic_handshake_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/base64.h" | 13 #include "base/base64.h" |
14 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
| 16 #include "base/compiler_specific.h" |
16 #include "base/containers/hash_tables.h" | 17 #include "base/containers/hash_tables.h" |
17 #include "base/logging.h" | 18 #include "base/logging.h" |
18 #include "base/metrics/histogram.h" | 19 #include "base/metrics/histogram.h" |
19 #include "base/metrics/sparse_histogram.h" | 20 #include "base/metrics/sparse_histogram.h" |
20 #include "base/stl_util.h" | 21 #include "base/stl_util.h" |
21 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
22 #include "base/strings/string_piece.h" | 23 #include "base/strings/string_piece.h" |
23 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
24 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
25 #include "base/time/time.h" | 26 #include "base/time/time.h" |
(...skipping 13 matching lines...) Expand all Loading... |
39 #include "net/websockets/websocket_deflater.h" | 40 #include "net/websockets/websocket_deflater.h" |
40 #include "net/websockets/websocket_extension_parser.h" | 41 #include "net/websockets/websocket_extension_parser.h" |
41 #include "net/websockets/websocket_handshake_constants.h" | 42 #include "net/websockets/websocket_handshake_constants.h" |
42 #include "net/websockets/websocket_handshake_handler.h" | 43 #include "net/websockets/websocket_handshake_handler.h" |
43 #include "net/websockets/websocket_handshake_request_info.h" | 44 #include "net/websockets/websocket_handshake_request_info.h" |
44 #include "net/websockets/websocket_handshake_response_info.h" | 45 #include "net/websockets/websocket_handshake_response_info.h" |
45 #include "net/websockets/websocket_stream.h" | 46 #include "net/websockets/websocket_stream.h" |
46 | 47 |
47 namespace net { | 48 namespace net { |
48 | 49 |
| 50 namespace { |
| 51 |
| 52 // TODO(yhirano): Remove these functions once http://crbug.com/399535 is fixed. |
| 53 NOINLINE void RunCallbackWithOk(const CompletionCallback& callback, |
| 54 int result) { |
| 55 DCHECK_EQ(result, OK); |
| 56 callback.Run(OK); |
| 57 } |
| 58 |
| 59 NOINLINE void RunCallbackWithInvalidResponseCausedByRedirect( |
| 60 const CompletionCallback& callback, |
| 61 int result) { |
| 62 DCHECK_EQ(result, ERR_INVALID_RESPONSE); |
| 63 callback.Run(ERR_INVALID_RESPONSE); |
| 64 } |
| 65 |
| 66 NOINLINE void RunCallbackWithInvalidResponse( |
| 67 const CompletionCallback& callback, |
| 68 int result) { |
| 69 DCHECK_EQ(result, ERR_INVALID_RESPONSE); |
| 70 callback.Run(ERR_INVALID_RESPONSE); |
| 71 } |
| 72 |
| 73 NOINLINE void RunCallback(const CompletionCallback& callback, int result) { |
| 74 callback.Run(result); |
| 75 } |
| 76 |
| 77 } // namespace |
| 78 |
49 // TODO(ricea): If more extensions are added, replace this with a more general | 79 // TODO(ricea): If more extensions are added, replace this with a more general |
50 // mechanism. | 80 // mechanism. |
51 struct WebSocketExtensionParams { | 81 struct WebSocketExtensionParams { |
52 WebSocketExtensionParams() | 82 WebSocketExtensionParams() |
53 : deflate_enabled(false), | 83 : deflate_enabled(false), |
54 client_window_bits(15), | 84 client_window_bits(15), |
55 deflate_mode(WebSocketDeflater::TAKE_OVER_CONTEXT) {} | 85 deflate_mode(WebSocketDeflater::TAKE_OVER_CONTEXT) {} |
56 | 86 |
57 bool deflate_enabled; | 87 bool deflate_enabled; |
58 int client_window_bits; | 88 int client_window_bits; |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 // HttpStreamParser uses a weak pointer when reading from the | 453 // HttpStreamParser uses a weak pointer when reading from the |
424 // socket, so it won't be called back after being destroyed. The | 454 // socket, so it won't be called back after being destroyed. The |
425 // HttpStreamParser is owned by HttpBasicState which is owned by this object, | 455 // HttpStreamParser is owned by HttpBasicState which is owned by this object, |
426 // so this use of base::Unretained() is safe. | 456 // so this use of base::Unretained() is safe. |
427 int rv = parser()->ReadResponseHeaders( | 457 int rv = parser()->ReadResponseHeaders( |
428 base::Bind(&WebSocketBasicHandshakeStream::ReadResponseHeadersCallback, | 458 base::Bind(&WebSocketBasicHandshakeStream::ReadResponseHeadersCallback, |
429 base::Unretained(this), | 459 base::Unretained(this), |
430 callback)); | 460 callback)); |
431 if (rv == ERR_IO_PENDING) | 461 if (rv == ERR_IO_PENDING) |
432 return rv; | 462 return rv; |
433 return ValidateResponse(rv); | 463 bool is_redirect = false; |
| 464 return ValidateResponse(rv, &is_redirect); |
434 } | 465 } |
435 | 466 |
436 int WebSocketBasicHandshakeStream::ReadResponseBody( | 467 int WebSocketBasicHandshakeStream::ReadResponseBody( |
437 IOBuffer* buf, | 468 IOBuffer* buf, |
438 int buf_len, | 469 int buf_len, |
439 const CompletionCallback& callback) { | 470 const CompletionCallback& callback) { |
440 return parser()->ReadResponseBody(buf, buf_len, callback); | 471 return parser()->ReadResponseBody(buf, buf_len, callback); |
441 } | 472 } |
442 | 473 |
443 void WebSocketBasicHandshakeStream::Close(bool not_reusable) { | 474 void WebSocketBasicHandshakeStream::Close(bool not_reusable) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 } | 559 } |
529 | 560 |
530 void WebSocketBasicHandshakeStream::SetWebSocketKeyForTesting( | 561 void WebSocketBasicHandshakeStream::SetWebSocketKeyForTesting( |
531 const std::string& key) { | 562 const std::string& key) { |
532 handshake_challenge_for_testing_.reset(new std::string(key)); | 563 handshake_challenge_for_testing_.reset(new std::string(key)); |
533 } | 564 } |
534 | 565 |
535 void WebSocketBasicHandshakeStream::ReadResponseHeadersCallback( | 566 void WebSocketBasicHandshakeStream::ReadResponseHeadersCallback( |
536 const CompletionCallback& callback, | 567 const CompletionCallback& callback, |
537 int result) { | 568 int result) { |
538 callback.Run(ValidateResponse(result)); | 569 bool is_redirect = false; |
| 570 int rv = ValidateResponse(result, &is_redirect); |
| 571 |
| 572 // TODO(yhirano): Simplify this statement once http://crbug.com/399535 is |
| 573 // fixed. |
| 574 switch (rv) { |
| 575 case OK: |
| 576 RunCallbackWithOk(callback, rv); |
| 577 break; |
| 578 case ERR_INVALID_RESPONSE: |
| 579 if (is_redirect) |
| 580 RunCallbackWithInvalidResponseCausedByRedirect(callback, rv); |
| 581 else |
| 582 RunCallbackWithInvalidResponse(callback, rv); |
| 583 break; |
| 584 default: |
| 585 RunCallback(callback, rv); |
| 586 break; |
| 587 } |
539 } | 588 } |
540 | 589 |
541 void WebSocketBasicHandshakeStream::OnFinishOpeningHandshake() { | 590 void WebSocketBasicHandshakeStream::OnFinishOpeningHandshake() { |
542 DCHECK(http_response_info_); | 591 DCHECK(http_response_info_); |
543 WebSocketDispatchOnFinishOpeningHandshake(connect_delegate_, | 592 WebSocketDispatchOnFinishOpeningHandshake(connect_delegate_, |
544 url_, | 593 url_, |
545 http_response_info_->headers, | 594 http_response_info_->headers, |
546 http_response_info_->response_time); | 595 http_response_info_->response_time); |
547 } | 596 } |
548 | 597 |
549 int WebSocketBasicHandshakeStream::ValidateResponse(int rv) { | 598 int WebSocketBasicHandshakeStream::ValidateResponse(int rv, |
| 599 bool* is_redirect) { |
550 DCHECK(http_response_info_); | 600 DCHECK(http_response_info_); |
| 601 *is_redirect = false; |
551 // Most net errors happen during connection, so they are not seen by this | 602 // Most net errors happen during connection, so they are not seen by this |
552 // method. The histogram for error codes is created in | 603 // method. The histogram for error codes is created in |
553 // Delegate::OnResponseStarted in websocket_stream.cc instead. | 604 // Delegate::OnResponseStarted in websocket_stream.cc instead. |
554 if (rv >= 0) { | 605 if (rv >= 0) { |
555 const HttpResponseHeaders* headers = http_response_info_->headers.get(); | 606 const HttpResponseHeaders* headers = http_response_info_->headers.get(); |
556 const int response_code = headers->response_code(); | 607 const int response_code = headers->response_code(); |
| 608 *is_redirect = HttpResponseHeaders::IsRedirectResponseCode(response_code); |
557 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.WebSocket.ResponseCode", response_code); | 609 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.WebSocket.ResponseCode", response_code); |
558 switch (response_code) { | 610 switch (response_code) { |
559 case HTTP_SWITCHING_PROTOCOLS: | 611 case HTTP_SWITCHING_PROTOCOLS: |
560 OnFinishOpeningHandshake(); | 612 OnFinishOpeningHandshake(); |
561 return ValidateUpgradeResponse(headers); | 613 return ValidateUpgradeResponse(headers); |
562 | 614 |
563 // We need to pass these through for authentication to work. | 615 // We need to pass these through for authentication to work. |
564 case HTTP_UNAUTHORIZED: | 616 case HTTP_UNAUTHORIZED: |
565 case HTTP_PROXY_AUTHENTICATION_REQUIRED: | 617 case HTTP_PROXY_AUTHENTICATION_REQUIRED: |
566 return OK; | 618 return OK; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 set_failure_message("Error during WebSocket handshake: " + failure_message); | 670 set_failure_message("Error during WebSocket handshake: " + failure_message); |
619 return ERR_INVALID_RESPONSE; | 671 return ERR_INVALID_RESPONSE; |
620 } | 672 } |
621 | 673 |
622 void WebSocketBasicHandshakeStream::set_failure_message( | 674 void WebSocketBasicHandshakeStream::set_failure_message( |
623 const std::string& failure_message) { | 675 const std::string& failure_message) { |
624 *failure_message_ = failure_message; | 676 *failure_message_ = failure_message; |
625 } | 677 } |
626 | 678 |
627 } // namespace net | 679 } // namespace net |
OLD | NEW |