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