| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_ |
| #define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_ |
| |
| // This file is included from net/http files. |
| // Since net/http can be built without linking net/websockets code, |
| // this file must not introduce any link-time dependencies on websockets. |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/weak_ptr.h" |
| #include "base/supports_user_data.h" |
| #include "net/base/net_export.h" |
| #include "net/http/http_stream.h" |
| #include "net/quic/quic_chromium_client_session.h" |
| #include "net/websockets/websocket_deflate_parameters.h" |
| #include "net/websockets/websocket_stream.h" |
| |
| namespace net { |
| |
| class ClientSocketHandle; |
| class SpdySession; |
| class HttpRequestHeaders; |
| class HttpResponseHeaders; |
| class WebSocketEndpointLockManager; |
| |
| // WebSocketHandshakeStreamBase is the base class of |
| // WebSocketBasicHandshakeStream. net/http code uses this interface to handle |
| // WebSocketBasicHandshakeStream when it needs to be treated differently from |
| // HttpStreamBase. |
| class NET_EXPORT WebSocketHandshakeStreamBase : public HttpStream { |
| public: |
| // These entries must match histogram Net.WebSocket.HandshakeResult2. |
| // Do not change or reuse values. |
| enum class HandshakeResult { |
| // Handshake not completed via Upgrade over HTTP/1 connection. |
| INCOMPLETE = 0, |
| // Server responded to Upgrade request with invalid status. |
| INVALID_STATUS = 1, |
| // Server responded to Upgrade request with empty response. |
| EMPTY_RESPONSE = 2, |
| // Server responded to Upgrade request with 101 status but there was some |
| // other network error. |
| FAILED_SWITCHING_PROTOCOLS = 3, |
| // Server responded to Upgrade request with invalid Upgrade header. |
| FAILED_UPGRADE = 4, |
| // Server responded to Upgrade request with invalid Sec-WebSocket-Accept |
| // header. |
| FAILED_ACCEPT = 5, |
| // Server responded to Upgrade request with invalid Connection header. |
| FAILED_CONNECTION = 6, |
| // Server responded to Upgrade request with invalid Sec-WebSocket-Protocol |
| // header. |
| FAILED_SUBPROTO = 7, |
| // Server responded to Upgrade request with invalid Sec-WebSocket-Extensions |
| // header. |
| FAILED_EXTENSIONS = 8, |
| // Upgrade request failed due to other network error. |
| FAILED = 9, |
| // Connected via Upgrade over HTTP/1 connection. |
| CONNECTED = 10, |
| // Handshake not completed over an HTTP/2 connection. |
| HTTP2_INCOMPLETE = 11, |
| // Server responded to WebSocket request over an HTTP/2 connection with |
| // invalid status code. |
| HTTP2_INVALID_STATUS = 12, |
| // Server responded to WebSocket request over an HTTP/2 connection with |
| // invalid sec-websocket-protocol header. |
| HTTP2_FAILED_SUBPROTO = 13, |
| // Server responded to WebSocket request over an HTTP/2 connection with |
| // invalid sec-websocket-extensions header. |
| HTTP2_FAILED_EXTENSIONS = 14, |
| // WebSocket request over an HTTP/2 connection failed with some other error. |
| HTTP2_FAILED = 15, |
| // Connected over an HTTP/2 connection. |
| HTTP2_CONNECTED = 16, |
| // Handshake not completed over an HTTP/3 connection. |
| HTTP3_INCOMPLETE = 17, |
| // Server responded to WebSocket request over an HTTP/3 connection with |
| // invalid status code. |
| HTTP3_INVALID_STATUS = 18, |
| // Server responded to WebSocket request over an HTTP/3 connection with |
| // invalid sec-websocket-protocol header. |
| HTTP3_FAILED_SUBPROTO = 19, |
| // Server responded to WebSocket request over an HTTP/3 connection with |
| // invalid sec-websocket-extensions header. |
| HTTP3_FAILED_EXTENSIONS = 20, |
| // WebSocket request over an HTTP/3 connection failed with some other error. |
| HTTP3_FAILED = 21, |
| // Connected over an HTTP/3 connection. |
| HTTP3_CONNECTED = 22, |
| NUM_HANDSHAKE_RESULT_TYPES = 23 |
| }; |
| |
| WebSocketHandshakeStreamBase() = default; |
| |
| WebSocketHandshakeStreamBase(const WebSocketHandshakeStreamBase&) = delete; |
| WebSocketHandshakeStreamBase& operator=(const WebSocketHandshakeStreamBase&) = |
| delete; |
| |
| ~WebSocketHandshakeStreamBase() override = default; |
| |
| // An object that stores data needed for the creation of a |
| // WebSocketBasicHandshakeStream object. A new CreateHelper is used for each |
| // WebSocket connection. |
| class NET_EXPORT_PRIVATE CreateHelper : public base::SupportsUserData::Data { |
| public: |
| ~CreateHelper() override = default; |
| |
| // Create a WebSocketBasicHandshakeStream. This is called after the |
| // underlying connection has been established but before any handshake data |
| // has been transferred. This can be called more than once in the case that |
| // HTTP authentication is needed. |
| virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream( |
| std::unique_ptr<ClientSocketHandle> connection, |
| bool using_proxy, |
| WebSocketEndpointLockManager* websocket_endpoint_lock_manager) = 0; |
| |
| // Create a WebSocketHttp2HandshakeStream. This is called after the |
| // underlying HTTP/2 connection has been established but before the stream |
| // has been opened. This cannot be called more than once. |
| virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream( |
| base::WeakPtr<SpdySession> session, |
| std::set<std::string> dns_aliases) = 0; |
| |
| // Create a WebSocketHttp3HandshakeStream. This is called after the |
| // underlying HTTP/3 connection has been established but before the stream |
| // has been opened. This cannot be called more than once. |
| virtual std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream( |
| std::unique_ptr<QuicChromiumClientSession::Handle> session, |
| std::set<std::string> dns_aliases) = 0; |
| }; |
| |
| // After the handshake has completed, this method creates a WebSocketStream |
| // (of the appropriate type) from the WebSocketHandshakeStreamBase object. |
| // The WebSocketHandshakeStreamBase object is unusable after Upgrade() has |
| // been called. |
| virtual std::unique_ptr<WebSocketStream> Upgrade() = 0; |
| |
| // Returns true if a read from the stream will succeed. This should be true |
| // even if the stream is at EOF. |
| virtual bool CanReadFromStream() const = 0; |
| |
| void SetRequestHeadersCallback(RequestHeadersCallback callback) override {} |
| |
| static std::string MultipleHeaderValuesMessage( |
| const std::string& header_name); |
| |
| // Subclasses need to implement this method so that the resulting weak |
| // pointers are invalidated as soon as the derived class is destroyed. |
| virtual base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() = 0; |
| |
| protected: |
| // TODO(ricea): If more extensions are added, replace this with a more general |
| // mechanism. |
| struct WebSocketExtensionParams { |
| bool deflate_enabled = false; |
| WebSocketDeflateParameters deflate_parameters; |
| }; |
| |
| static void AddVectorHeaderIfNonEmpty(const char* name, |
| const std::vector<std::string>& value, |
| HttpRequestHeaders* headers); |
| |
| static bool ValidateSubProtocol( |
| const HttpResponseHeaders* headers, |
| const std::vector<std::string>& requested_sub_protocols, |
| std::string* sub_protocol, |
| std::string* failure_message); |
| |
| static bool ValidateExtensions(const HttpResponseHeaders* headers, |
| std::string* accepted_extensions_descriptor, |
| std::string* failure_message, |
| WebSocketExtensionParams* params); |
| |
| void RecordHandshakeResult(HandshakeResult result); |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_ |