[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_ |
| 6 | #define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_ |
| 7 | |
| 8 | // This file is included from net/http files. |
| 9 | // Since net/http can be built without linking net/websockets code, |
| 10 | // this file must not introduce any link-time dependencies on websockets. |
| 11 | |
danakj | 9c5cab5 | 2016-04-16 00:54:33 | [diff] [blame] | 12 | #include <memory> |
[email protected] | 9686820 | 2014-01-09 10:38:04 | [diff] [blame] | 13 | #include <string> |
Bence Béky | b28709c2 | 2018-03-06 13:03:44 | [diff] [blame] | 14 | #include <vector> |
[email protected] | 9686820 | 2014-01-09 10:38:04 | [diff] [blame] | 15 | |
tfarina | ea94afc23 | 2015-10-20 04:23:36 | [diff] [blame] | 16 | #include "base/macros.h" |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 17 | #include "base/memory/weak_ptr.h" |
[email protected] | f4533ba | 2013-11-28 09:35:41 | [diff] [blame] | 18 | #include "base/supports_user_data.h" |
bnc | 81c46c1f | 2016-10-04 16:25:59 | [diff] [blame] | 19 | #include "net/base/net_export.h" |
yhirano | a7e05bb | 2014-11-06 05:40:39 | [diff] [blame] | 20 | #include "net/http/http_stream.h" |
Bence Béky | b28709c2 | 2018-03-06 13:03:44 | [diff] [blame] | 21 | #include "net/websockets/websocket_deflate_parameters.h" |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 22 | #include "net/websockets/websocket_stream.h" |
| 23 | |
| 24 | namespace net { |
| 25 | |
| 26 | class ClientSocketHandle; |
Bence Béky | 46bfbc1 | 2018-02-22 19:28:20 | [diff] [blame] | 27 | class SpdySession; |
Bence Béky | b28709c2 | 2018-03-06 13:03:44 | [diff] [blame] | 28 | class HttpRequestHeaders; |
| 29 | class HttpResponseHeaders; |
Bence Béky | da280c6 | 2018-04-12 15:08:37 | [diff] [blame] | 30 | class WebSocketEndpointLockManager; |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 31 | |
| 32 | // WebSocketHandshakeStreamBase is the base class of |
| 33 | // WebSocketBasicHandshakeStream. net/http code uses this interface to handle |
| 34 | // WebSocketBasicHandshakeStream when it needs to be treated differently from |
| 35 | // HttpStreamBase. |
yhirano | a7e05bb | 2014-11-06 05:40:39 | [diff] [blame] | 36 | class NET_EXPORT WebSocketHandshakeStreamBase : public HttpStream { |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 37 | public: |
Bence Béky | de0be31 | 2018-03-13 17:51:58 | [diff] [blame] | 38 | // These entries must match histogram Net.WebSocket.HandshakeResult2. |
| 39 | // Do not change or reuse values. |
| 40 | enum class HandshakeResult { |
| 41 | // Handshake not completed via Upgrade over HTTP/1 connection. |
| 42 | INCOMPLETE = 0, |
| 43 | // Server responded to Upgrade request with invalid status. |
| 44 | INVALID_STATUS = 1, |
| 45 | // Server responded to Upgrade request with empty response. |
| 46 | EMPTY_RESPONSE = 2, |
| 47 | // Server responded to Upgrade request with 101 status but there was some |
| 48 | // other network error. |
| 49 | FAILED_SWITCHING_PROTOCOLS = 3, |
| 50 | // Server responded to Upgrade request with invalid Upgrade header. |
| 51 | FAILED_UPGRADE = 4, |
| 52 | // Server responded to Upgrade request with invalid Sec-WebSocket-Accept |
| 53 | // header. |
| 54 | FAILED_ACCEPT = 5, |
| 55 | // Server responded to Upgrade request with invalid Connection header. |
| 56 | FAILED_CONNECTION = 6, |
| 57 | // Server responded to Upgrade request with invalid Sec-WebSocket-Protocol |
| 58 | // header. |
| 59 | FAILED_SUBPROTO = 7, |
| 60 | // Server responded to Upgrade request with invalid Sec-WebSocket-Extensions |
| 61 | // header. |
| 62 | FAILED_EXTENSIONS = 8, |
| 63 | // Upgrade request failed due to other network error. |
| 64 | FAILED = 9, |
| 65 | // Connected via Upgrade over HTTP/1 connection. |
| 66 | CONNECTED = 10, |
| 67 | // Handshake not completed over an HTTP/2 connection. |
| 68 | HTTP2_INCOMPLETE = 11, |
| 69 | // Server responded to WebSocket request over an HTTP/2 connection with |
| 70 | // invalid status code. |
| 71 | HTTP2_INVALID_STATUS = 12, |
| 72 | // Server responded to WebSocket request over an HTTP/2 connection with |
| 73 | // invalid sec-websocket-protocol header. |
| 74 | HTTP2_FAILED_SUBPROTO = 13, |
| 75 | // Server responded to WebSocket request over an HTTP/2 connection with |
| 76 | // invalid sec-websocket-extensions header. |
| 77 | HTTP2_FAILED_EXTENSIONS = 14, |
| 78 | // WebSocket request over an HTTP/2 connection failed with some other error. |
| 79 | HTTP2_FAILED = 15, |
| 80 | // Connected over an HTTP/2 connection. |
| 81 | HTTP2_CONNECTED = 16, |
| 82 | NUM_HANDSHAKE_RESULT_TYPES = 17 |
| 83 | }; |
| 84 | |
Bence Béky | b28709c2 | 2018-03-06 13:03:44 | [diff] [blame] | 85 | WebSocketHandshakeStreamBase() = default; |
| 86 | ~WebSocketHandshakeStreamBase() override = default; |
| 87 | |
[email protected] | efa9e73 | 2013-11-29 02:55:05 | [diff] [blame] | 88 | // An object that stores data needed for the creation of a |
| 89 | // WebSocketBasicHandshakeStream object. A new CreateHelper is used for each |
| 90 | // WebSocket connection. |
| 91 | class NET_EXPORT_PRIVATE CreateHelper : public base::SupportsUserData::Data { |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 92 | public: |
dcheng | b03027d | 2014-10-21 12:00:20 | [diff] [blame] | 93 | ~CreateHelper() override {} |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 94 | |
[email protected] | 7e841a5 | 2013-11-22 09:04:21 | [diff] [blame] | 95 | // Create a WebSocketBasicHandshakeStream. This is called after the |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 96 | // underlying connection has been established but before any handshake data |
[email protected] | efa9e73 | 2013-11-29 02:55:05 | [diff] [blame] | 97 | // has been transferred. This can be called more than once in the case that |
| 98 | // HTTP authentication is needed. |
bnc | 615cf2f | 2017-05-19 18:53:26 | [diff] [blame] | 99 | virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream( |
danakj | 9c5cab5 | 2016-04-16 00:54:33 | [diff] [blame] | 100 | std::unique_ptr<ClientSocketHandle> connection, |
Bence Béky | da280c6 | 2018-04-12 15:08:37 | [diff] [blame] | 101 | bool using_proxy, |
| 102 | WebSocketEndpointLockManager* websocket_endpoint_lock_manager) = 0; |
Bence Béky | 46bfbc1 | 2018-02-22 19:28:20 | [diff] [blame] | 103 | |
| 104 | // Create a WebSocketHttp2HandshakeStream. This is called after the |
| 105 | // underlying HTTP/2 connection has been established but before the stream |
| 106 | // has been opened. This cannot be called more than once. |
| 107 | virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream( |
| 108 | base::WeakPtr<SpdySession> session) = 0; |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 109 | }; |
| 110 | |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 111 | // After the handshake has completed, this method creates a WebSocketStream |
| 112 | // (of the appropriate type) from the WebSocketHandshakeStreamBase object. |
| 113 | // The WebSocketHandshakeStreamBase object is unusable after Upgrade() has |
| 114 | // been called. |
danakj | 9c5cab5 | 2016-04-16 00:54:33 | [diff] [blame] | 115 | virtual std::unique_ptr<WebSocketStream> Upgrade() = 0; |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 116 | |
Andrey Kosyakov | 83a6eee | 2017-08-14 19:20:04 | [diff] [blame] | 117 | void SetRequestHeadersCallback(RequestHeadersCallback callback) override {} |
| 118 | |
Bence Béky | b28709c2 | 2018-03-06 13:03:44 | [diff] [blame] | 119 | static std::string MultipleHeaderValuesMessage( |
| 120 | const std::string& header_name); |
| 121 | |
Bence Béky | ca0da43 | 2019-01-24 15:03:20 | [diff] [blame] | 122 | // Subclasses need to implement this method so that the resulting weak |
| 123 | // pointers are invalidated as soon as the derived class is destroyed. |
| 124 | virtual base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() = 0; |
| 125 | |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 126 | protected: |
Bence Béky | b28709c2 | 2018-03-06 13:03:44 | [diff] [blame] | 127 | // TODO(ricea): If more extensions are added, replace this with a more general |
| 128 | // mechanism. |
| 129 | struct WebSocketExtensionParams { |
| 130 | bool deflate_enabled = false; |
| 131 | WebSocketDeflateParameters deflate_parameters; |
| 132 | }; |
| 133 | |
| 134 | static void AddVectorHeaderIfNonEmpty(const char* name, |
| 135 | const std::vector<std::string>& value, |
| 136 | HttpRequestHeaders* headers); |
| 137 | |
| 138 | static bool ValidateSubProtocol( |
| 139 | const HttpResponseHeaders* headers, |
| 140 | const std::vector<std::string>& requested_sub_protocols, |
| 141 | std::string* sub_protocol, |
| 142 | std::string* failure_message); |
| 143 | |
| 144 | static bool ValidateExtensions(const HttpResponseHeaders* headers, |
| 145 | std::string* accepted_extensions_descriptor, |
| 146 | std::string* failure_message, |
| 147 | WebSocketExtensionParams* params); |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 148 | |
Bence Béky | de0be31 | 2018-03-13 17:51:58 | [diff] [blame] | 149 | void RecordHandshakeResult(HandshakeResult result); |
Bence Béky | de0be31 | 2018-03-13 17:51:58 | [diff] [blame] | 150 | |
[email protected] | a9cf2b9 | 2013-10-30 12:08:49 | [diff] [blame] | 151 | private: |
| 152 | DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeStreamBase); |
| 153 | }; |
| 154 | |
| 155 | } // namespace net |
| 156 | |
| 157 | #endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_ |