1 // Copyright 2013 The Chromium Authors 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 12 #include <memory> 13 #include <set> 14 #include <string> 15 #include <vector> 16 17 #include "base/memory/weak_ptr.h" 18 #include "base/supports_user_data.h" 19 #include "net/base/net_export.h" 20 #include "net/http/http_raw_request_headers.h" 21 #include "net/http/http_stream.h" 22 #include "net/quic/quic_chromium_client_session.h" 23 #include "net/websockets/websocket_deflate_parameters.h" 24 #include "net/websockets/websocket_stream.h" 25 26 namespace net { 27 28 class ClientSocketHandle; 29 class SpdySession; 30 class HttpRequestHeaders; 31 class HttpResponseHeaders; 32 class WebSocketEndpointLockManager; 33 class WebSocketStream; 34 35 // WebSocketHandshakeStreamBase is the base class of 36 // WebSocketBasicHandshakeStream. net/http code uses this interface to handle 37 // WebSocketBasicHandshakeStream when it needs to be treated differently from 38 // HttpStreamBase. 39 class NET_EXPORT WebSocketHandshakeStreamBase : public HttpStream { 40 public: 41 // These entries must match histogram Net.WebSocket.HandshakeResult2. 42 // Do not change or reuse values. 43 enum class HandshakeResult { 44 // Handshake not completed via Upgrade over HTTP/1 connection. 45 INCOMPLETE = 0, 46 // Server responded to Upgrade request with invalid status. 47 INVALID_STATUS = 1, 48 // Server responded to Upgrade request with empty response. 49 EMPTY_RESPONSE = 2, 50 // Server responded to Upgrade request with 101 status but there was some 51 // other network error. 52 FAILED_SWITCHING_PROTOCOLS = 3, 53 // Server responded to Upgrade request with invalid Upgrade header. 54 FAILED_UPGRADE = 4, 55 // Server responded to Upgrade request with invalid Sec-WebSocket-Accept 56 // header. 57 FAILED_ACCEPT = 5, 58 // Server responded to Upgrade request with invalid Connection header. 59 FAILED_CONNECTION = 6, 60 // Server responded to Upgrade request with invalid Sec-WebSocket-Protocol 61 // header. 62 FAILED_SUBPROTO = 7, 63 // Server responded to Upgrade request with invalid Sec-WebSocket-Extensions 64 // header. 65 FAILED_EXTENSIONS = 8, 66 // Upgrade request failed due to other network error. 67 FAILED = 9, 68 // Connected via Upgrade over HTTP/1 connection. 69 CONNECTED = 10, 70 // Handshake not completed over an HTTP/2 connection. 71 HTTP2_INCOMPLETE = 11, 72 // Server responded to WebSocket request over an HTTP/2 connection with 73 // invalid status code. 74 HTTP2_INVALID_STATUS = 12, 75 // Server responded to WebSocket request over an HTTP/2 connection with 76 // invalid sec-websocket-protocol header. 77 HTTP2_FAILED_SUBPROTO = 13, 78 // Server responded to WebSocket request over an HTTP/2 connection with 79 // invalid sec-websocket-extensions header. 80 HTTP2_FAILED_EXTENSIONS = 14, 81 // WebSocket request over an HTTP/2 connection failed with some other error. 82 HTTP2_FAILED = 15, 83 // Connected over an HTTP/2 connection. 84 HTTP2_CONNECTED = 16, 85 // Handshake not completed over an HTTP/3 connection. 86 HTTP3_INCOMPLETE = 17, 87 // Server responded to WebSocket request over an HTTP/3 connection with 88 // invalid status code. 89 HTTP3_INVALID_STATUS = 18, 90 // Server responded to WebSocket request over an HTTP/3 connection with 91 // invalid sec-websocket-protocol header. 92 HTTP3_FAILED_SUBPROTO = 19, 93 // Server responded to WebSocket request over an HTTP/3 connection with 94 // invalid sec-websocket-extensions header. 95 HTTP3_FAILED_EXTENSIONS = 20, 96 // WebSocket request over an HTTP/3 connection failed with some other error. 97 HTTP3_FAILED = 21, 98 // Connected over an HTTP/3 connection. 99 HTTP3_CONNECTED = 22, 100 NUM_HANDSHAKE_RESULT_TYPES = 23 101 }; 102 103 WebSocketHandshakeStreamBase() = default; 104 105 WebSocketHandshakeStreamBase(const WebSocketHandshakeStreamBase&) = delete; 106 WebSocketHandshakeStreamBase& operator=(const WebSocketHandshakeStreamBase&) = 107 delete; 108 109 ~WebSocketHandshakeStreamBase() override = default; 110 111 // An object that stores data needed for the creation of a 112 // WebSocketBasicHandshakeStream object. A new CreateHelper is used for each 113 // WebSocket connection. 114 class NET_EXPORT_PRIVATE CreateHelper : public base::SupportsUserData::Data { 115 public: 116 ~CreateHelper() override = default; 117 118 // Create a WebSocketBasicHandshakeStream. This is called after the 119 // underlying connection has been established but before any handshake data 120 // has been transferred. This can be called more than once in the case that 121 // HTTP authentication is needed. 122 virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream( 123 std::unique_ptr<ClientSocketHandle> connection, 124 bool using_proxy, 125 WebSocketEndpointLockManager* websocket_endpoint_lock_manager) = 0; 126 127 // Create a WebSocketHttp2HandshakeStream. This is called after the 128 // underlying HTTP/2 connection has been established but before the stream 129 // has been opened. This cannot be called more than once. 130 virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream( 131 base::WeakPtr<SpdySession> session, 132 std::set<std::string> dns_aliases) = 0; 133 134 // Create a WebSocketHttp3HandshakeStream. This is called after the 135 // underlying HTTP/3 connection has been established but before the stream 136 // has been opened. This cannot be called more than once. 137 virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream( 138 std::unique_ptr<QuicChromiumClientSession::Handle> session, 139 std::set<std::string> dns_aliases) = 0; 140 }; 141 142 // After the handshake has completed, this method creates a WebSocketStream 143 // (of the appropriate type) from the WebSocketHandshakeStreamBase object. 144 // The WebSocketHandshakeStreamBase object is unusable after Upgrade() has 145 // been called. 146 virtual std::unique_ptr<WebSocketStream> Upgrade() = 0; 147 148 // Returns true if a read from the stream will succeed. This should be true 149 // even if the stream is at EOF. 150 virtual bool CanReadFromStream() const = 0; 151 SetRequestHeadersCallback(RequestHeadersCallback callback)152 void SetRequestHeadersCallback(RequestHeadersCallback callback) override {} 153 154 static std::string MultipleHeaderValuesMessage( 155 const std::string& header_name); 156 157 // Subclasses need to implement this method so that the resulting weak 158 // pointers are invalidated as soon as the derived class is destroyed. 159 virtual base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() = 0; 160 161 protected: 162 // TODO(ricea): If more extensions are added, replace this with a more general 163 // mechanism. 164 struct WebSocketExtensionParams { 165 bool deflate_enabled = false; 166 WebSocketDeflateParameters deflate_parameters; 167 }; 168 169 static void AddVectorHeaderIfNonEmpty(const char* name, 170 const std::vector<std::string>& value, 171 HttpRequestHeaders* headers); 172 173 static bool ValidateSubProtocol( 174 const HttpResponseHeaders* headers, 175 const std::vector<std::string>& requested_sub_protocols, 176 std::string* sub_protocol, 177 std::string* failure_message); 178 179 static bool ValidateExtensions(const HttpResponseHeaders* headers, 180 std::string* accepted_extensions_descriptor, 181 std::string* failure_message, 182 WebSocketExtensionParams* params); 183 184 void RecordHandshakeResult(HandshakeResult result); 185 }; 186 187 } // namespace net 188 189 #endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_ 190