xref: /aosp_15_r20/external/cronet/net/websockets/websocket_handshake_stream_base.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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