xref: /aosp_15_r20/external/cronet/net/websockets/websocket_channel.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker #include <optional>
13*6777b538SAndroid Build Coastguard Worker #include <string>
14*6777b538SAndroid Build Coastguard Worker #include <vector>
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include "base/containers/queue.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/i18n/streaming_utf8_validator.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/memory/scoped_refptr.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/timer/timer.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_event_interface.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_frame.h"
27*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_stream.h"
28*6777b538SAndroid Build Coastguard Worker #include "url/gurl.h"
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker namespace url {
31*6777b538SAndroid Build Coastguard Worker class Origin;
32*6777b538SAndroid Build Coastguard Worker }  // namespace url
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker namespace net {
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker class AuthChallengeInfo;
37*6777b538SAndroid Build Coastguard Worker class AuthCredentials;
38*6777b538SAndroid Build Coastguard Worker class HttpRequestHeaders;
39*6777b538SAndroid Build Coastguard Worker class HttpResponseHeaders;
40*6777b538SAndroid Build Coastguard Worker class IOBuffer;
41*6777b538SAndroid Build Coastguard Worker class IPEndPoint;
42*6777b538SAndroid Build Coastguard Worker class IsolationInfo;
43*6777b538SAndroid Build Coastguard Worker class NetLogWithSource;
44*6777b538SAndroid Build Coastguard Worker class SSLInfo;
45*6777b538SAndroid Build Coastguard Worker class SiteForCookies;
46*6777b538SAndroid Build Coastguard Worker class URLRequest;
47*6777b538SAndroid Build Coastguard Worker class URLRequestContext;
48*6777b538SAndroid Build Coastguard Worker struct NetworkTrafficAnnotationTag;
49*6777b538SAndroid Build Coastguard Worker struct WebSocketHandshakeRequestInfo;
50*6777b538SAndroid Build Coastguard Worker struct WebSocketHandshakeResponseInfo;
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker // Transport-independent implementation of WebSockets. Implements protocol
53*6777b538SAndroid Build Coastguard Worker // semantics that do not depend on the underlying transport. Provides the
54*6777b538SAndroid Build Coastguard Worker // interface to the content layer. Some WebSocket concepts are used here without
55*6777b538SAndroid Build Coastguard Worker // definition; please see the RFC at http://tools.ietf.org/html/rfc6455 for
56*6777b538SAndroid Build Coastguard Worker // clarification.
57*6777b538SAndroid Build Coastguard Worker class NET_EXPORT WebSocketChannel {
58*6777b538SAndroid Build Coastguard Worker  public:
59*6777b538SAndroid Build Coastguard Worker   // The type of a WebSocketStream creator callback. Must match the signature of
60*6777b538SAndroid Build Coastguard Worker   // WebSocketStream::CreateAndConnectStream().
61*6777b538SAndroid Build Coastguard Worker   typedef base::OnceCallback<std::unique_ptr<WebSocketStreamRequest>(
62*6777b538SAndroid Build Coastguard Worker       const GURL&,
63*6777b538SAndroid Build Coastguard Worker       const std::vector<std::string>&,
64*6777b538SAndroid Build Coastguard Worker       const url::Origin&,
65*6777b538SAndroid Build Coastguard Worker       const SiteForCookies&,
66*6777b538SAndroid Build Coastguard Worker       bool,
67*6777b538SAndroid Build Coastguard Worker       const IsolationInfo&,
68*6777b538SAndroid Build Coastguard Worker       const HttpRequestHeaders&,
69*6777b538SAndroid Build Coastguard Worker       URLRequestContext*,
70*6777b538SAndroid Build Coastguard Worker       const NetLogWithSource&,
71*6777b538SAndroid Build Coastguard Worker       NetworkTrafficAnnotationTag,
72*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<WebSocketStream::ConnectDelegate>)>
73*6777b538SAndroid Build Coastguard Worker       WebSocketStreamRequestCreationCallback;
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker   // Methods which return a value of type ChannelState may delete |this|. If the
76*6777b538SAndroid Build Coastguard Worker   // return value is CHANNEL_DELETED, then the caller must return without making
77*6777b538SAndroid Build Coastguard Worker   // any further access to member variables or methods.
78*6777b538SAndroid Build Coastguard Worker   enum ChannelState { CHANNEL_ALIVE, CHANNEL_DELETED };
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker   // Creates a new WebSocketChannel in an idle state.
81*6777b538SAndroid Build Coastguard Worker   // SendAddChannelRequest() must be called immediately afterwards to start the
82*6777b538SAndroid Build Coastguard Worker   // connection process.
83*6777b538SAndroid Build Coastguard Worker   WebSocketChannel(std::unique_ptr<WebSocketEventInterface> event_interface,
84*6777b538SAndroid Build Coastguard Worker                    URLRequestContext* url_request_context);
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker   WebSocketChannel(const WebSocketChannel&) = delete;
87*6777b538SAndroid Build Coastguard Worker   WebSocketChannel& operator=(const WebSocketChannel&) = delete;
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   virtual ~WebSocketChannel();
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker   // Starts the connection process.
92*6777b538SAndroid Build Coastguard Worker   void SendAddChannelRequest(
93*6777b538SAndroid Build Coastguard Worker       const GURL& socket_url,
94*6777b538SAndroid Build Coastguard Worker       const std::vector<std::string>& requested_protocols,
95*6777b538SAndroid Build Coastguard Worker       const url::Origin& origin,
96*6777b538SAndroid Build Coastguard Worker       const SiteForCookies& site_for_cookies,
97*6777b538SAndroid Build Coastguard Worker       bool has_storage_access,
98*6777b538SAndroid Build Coastguard Worker       const IsolationInfo& isolation_info,
99*6777b538SAndroid Build Coastguard Worker       const HttpRequestHeaders& additional_headers,
100*6777b538SAndroid Build Coastguard Worker       NetworkTrafficAnnotationTag traffic_annotation);
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker   // Sends a data frame to the remote side. It is the responsibility of the
103*6777b538SAndroid Build Coastguard Worker   // caller to ensure that they have sufficient send quota to send this data,
104*6777b538SAndroid Build Coastguard Worker   // otherwise the connection will be closed without sending. |fin| indicates
105*6777b538SAndroid Build Coastguard Worker   // the last frame in a message, equivalent to "FIN" as specified in section
106*6777b538SAndroid Build Coastguard Worker   // 5.2 of RFC6455. |buffer->data()| is the "Payload Data". If |op_code| is
107*6777b538SAndroid Build Coastguard Worker   // kOpCodeText, or it is kOpCodeContinuation and the type the message is
108*6777b538SAndroid Build Coastguard Worker   // Text, then |buffer->data()| must be a chunk of a valid UTF-8 message,
109*6777b538SAndroid Build Coastguard Worker   // however there is no requirement for |buffer->data()| to be split on
110*6777b538SAndroid Build Coastguard Worker   // character boundaries. Calling SendFrame may result in synchronous calls to
111*6777b538SAndroid Build Coastguard Worker   // |event_interface_| which may result in this object being deleted. In that
112*6777b538SAndroid Build Coastguard Worker   // case, the return value will be CHANNEL_DELETED.
113*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState SendFrame(bool fin,
114*6777b538SAndroid Build Coastguard Worker                                        WebSocketFrameHeader::OpCode op_code,
115*6777b538SAndroid Build Coastguard Worker                                        scoped_refptr<IOBuffer> buffer,
116*6777b538SAndroid Build Coastguard Worker                                        size_t buffer_size);
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   // Calls WebSocketStream::ReadFrames() with the appropriate arguments. Stops
119*6777b538SAndroid Build Coastguard Worker   // calling ReadFrames if no writable buffer in dataframe or WebSocketStream
120*6777b538SAndroid Build Coastguard Worker   // starts async read.
121*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState ReadFrames();
122*6777b538SAndroid Build Coastguard Worker 
123*6777b538SAndroid Build Coastguard Worker   // Starts the closing handshake for a client-initiated shutdown of the
124*6777b538SAndroid Build Coastguard Worker   // connection. There is no API to close the connection without a closing
125*6777b538SAndroid Build Coastguard Worker   // handshake, but destroying the WebSocketChannel object while connected will
126*6777b538SAndroid Build Coastguard Worker   // effectively do that. |code| must be in the range 1000-4999. |reason| should
127*6777b538SAndroid Build Coastguard Worker   // be a valid UTF-8 string or empty.
128*6777b538SAndroid Build Coastguard Worker   //
129*6777b538SAndroid Build Coastguard Worker   // Calling this function may result in synchronous calls to |event_interface_|
130*6777b538SAndroid Build Coastguard Worker   // which may result in this object being deleted. In that case, the return
131*6777b538SAndroid Build Coastguard Worker   // value will be CHANNEL_DELETED.
132*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState StartClosingHandshake(uint16_t code,
133*6777b538SAndroid Build Coastguard Worker                                                    const std::string& reason);
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   // Starts the connection process, using a specified creator callback rather
136*6777b538SAndroid Build Coastguard Worker   // than the default. This is exposed for testing.
137*6777b538SAndroid Build Coastguard Worker   void SendAddChannelRequestForTesting(
138*6777b538SAndroid Build Coastguard Worker       const GURL& socket_url,
139*6777b538SAndroid Build Coastguard Worker       const std::vector<std::string>& requested_protocols,
140*6777b538SAndroid Build Coastguard Worker       const url::Origin& origin,
141*6777b538SAndroid Build Coastguard Worker       const SiteForCookies& site_for_cookies,
142*6777b538SAndroid Build Coastguard Worker       bool has_storage_access,
143*6777b538SAndroid Build Coastguard Worker       const IsolationInfo& isolation_info,
144*6777b538SAndroid Build Coastguard Worker       const HttpRequestHeaders& additional_headers,
145*6777b538SAndroid Build Coastguard Worker       NetworkTrafficAnnotationTag traffic_annotation,
146*6777b538SAndroid Build Coastguard Worker       WebSocketStreamRequestCreationCallback callback);
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker   // The default timout for the closing handshake is a sensible value (see
149*6777b538SAndroid Build Coastguard Worker   // kClosingHandshakeTimeoutSeconds in websocket_channel.cc). However, we can
150*6777b538SAndroid Build Coastguard Worker   // set it to a very small value for testing purposes.
151*6777b538SAndroid Build Coastguard Worker   void SetClosingHandshakeTimeoutForTesting(base::TimeDelta delay);
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker   // The default timout for the underlying connection close is a sensible value
154*6777b538SAndroid Build Coastguard Worker   // (see kUnderlyingConnectionCloseTimeoutSeconds in websocket_channel.cc).
155*6777b538SAndroid Build Coastguard Worker   // However, we can set it to a very small value for testing purposes.
156*6777b538SAndroid Build Coastguard Worker   void SetUnderlyingConnectionCloseTimeoutForTesting(base::TimeDelta delay);
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker   // Called when the stream starts the WebSocket Opening Handshake.
159*6777b538SAndroid Build Coastguard Worker   // This method is public for testing.
160*6777b538SAndroid Build Coastguard Worker   void OnStartOpeningHandshake(
161*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<WebSocketHandshakeRequestInfo> request);
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker  private:
164*6777b538SAndroid Build Coastguard Worker   // The object passes through a linear progression of states from
165*6777b538SAndroid Build Coastguard Worker   // FRESHLY_CONSTRUCTED to CLOSED, except that the SEND_CLOSED and RECV_CLOSED
166*6777b538SAndroid Build Coastguard Worker   // states may be skipped in case of error.
167*6777b538SAndroid Build Coastguard Worker   enum State {
168*6777b538SAndroid Build Coastguard Worker     FRESHLY_CONSTRUCTED,
169*6777b538SAndroid Build Coastguard Worker     CONNECTING,
170*6777b538SAndroid Build Coastguard Worker     CONNECTED,
171*6777b538SAndroid Build Coastguard Worker     SEND_CLOSED,  // A Close frame has been sent but not received.
172*6777b538SAndroid Build Coastguard Worker     RECV_CLOSED,  // Used briefly between receiving a Close frame and sending
173*6777b538SAndroid Build Coastguard Worker                   // the response. Once the response is sent, the state changes
174*6777b538SAndroid Build Coastguard Worker                   // to CLOSED.
175*6777b538SAndroid Build Coastguard Worker     CLOSE_WAIT,   // The Closing Handshake has completed, but the remote server
176*6777b538SAndroid Build Coastguard Worker                   // has not yet closed the connection.
177*6777b538SAndroid Build Coastguard Worker     CLOSED,       // The Closing Handshake has completed and the connection
178*6777b538SAndroid Build Coastguard Worker                   // has been closed; or the connection is failed.
179*6777b538SAndroid Build Coastguard Worker   };
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker   // Implementation of WebSocketStream::ConnectDelegate for
182*6777b538SAndroid Build Coastguard Worker   // WebSocketChannel. WebSocketChannel does not inherit from
183*6777b538SAndroid Build Coastguard Worker   // WebSocketStream::ConnectDelegate directly to avoid cluttering the public
184*6777b538SAndroid Build Coastguard Worker   // interface with the implementation of those methods, and because the
185*6777b538SAndroid Build Coastguard Worker   // lifetime of a WebSocketChannel is longer than the lifetime of the
186*6777b538SAndroid Build Coastguard Worker   // connection process.
187*6777b538SAndroid Build Coastguard Worker   class ConnectDelegate;
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker   // Starts the connection process, using the supplied stream request creation
190*6777b538SAndroid Build Coastguard Worker   // callback.
191*6777b538SAndroid Build Coastguard Worker   void SendAddChannelRequestWithSuppliedCallback(
192*6777b538SAndroid Build Coastguard Worker       const GURL& socket_url,
193*6777b538SAndroid Build Coastguard Worker       const std::vector<std::string>& requested_protocols,
194*6777b538SAndroid Build Coastguard Worker       const url::Origin& origin,
195*6777b538SAndroid Build Coastguard Worker       const SiteForCookies& site_for_cookies,
196*6777b538SAndroid Build Coastguard Worker       bool has_storage_access,
197*6777b538SAndroid Build Coastguard Worker       const IsolationInfo& isolation_info,
198*6777b538SAndroid Build Coastguard Worker       const HttpRequestHeaders& additional_headers,
199*6777b538SAndroid Build Coastguard Worker       NetworkTrafficAnnotationTag traffic_annotation,
200*6777b538SAndroid Build Coastguard Worker       WebSocketStreamRequestCreationCallback callback);
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   // Called when a URLRequest is created for handshaking.
203*6777b538SAndroid Build Coastguard Worker   void OnCreateURLRequest(URLRequest* request);
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker   // Called when a URLRequest's OnConnected is called. Forwards the call to the
206*6777b538SAndroid Build Coastguard Worker   // |event_interface_|
207*6777b538SAndroid Build Coastguard Worker   void OnURLRequestConnected(URLRequest* request, const TransportInfo& info);
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker   // Success callback from WebSocketStream::CreateAndConnectStream(). Reports
210*6777b538SAndroid Build Coastguard Worker   // success to the event interface. May delete |this|.
211*6777b538SAndroid Build Coastguard Worker   void OnConnectSuccess(
212*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<WebSocketStream> stream,
213*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<WebSocketHandshakeResponseInfo> response);
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker   // Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
216*6777b538SAndroid Build Coastguard Worker   // failure to the event interface. May delete |this|.
217*6777b538SAndroid Build Coastguard Worker   void OnConnectFailure(const std::string& message,
218*6777b538SAndroid Build Coastguard Worker                         int net_error,
219*6777b538SAndroid Build Coastguard Worker                         std::optional<int> response_code);
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker   // SSL certificate error callback from
222*6777b538SAndroid Build Coastguard Worker   // WebSocketStream::CreateAndConnectStream(). Forwards the request to the
223*6777b538SAndroid Build Coastguard Worker   // event interface.
224*6777b538SAndroid Build Coastguard Worker   void OnSSLCertificateError(
225*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks>
226*6777b538SAndroid Build Coastguard Worker           ssl_error_callbacks,
227*6777b538SAndroid Build Coastguard Worker       int net_error,
228*6777b538SAndroid Build Coastguard Worker       const SSLInfo& ssl_info,
229*6777b538SAndroid Build Coastguard Worker       bool fatal);
230*6777b538SAndroid Build Coastguard Worker 
231*6777b538SAndroid Build Coastguard Worker   // Authentication request from WebSocketStream::CreateAndConnectStream().
232*6777b538SAndroid Build Coastguard Worker   // Forwards the request to the event interface.
233*6777b538SAndroid Build Coastguard Worker   int OnAuthRequired(const AuthChallengeInfo& auth_info,
234*6777b538SAndroid Build Coastguard Worker                      scoped_refptr<HttpResponseHeaders> response_headers,
235*6777b538SAndroid Build Coastguard Worker                      const IPEndPoint& remote_endpoint,
236*6777b538SAndroid Build Coastguard Worker                      base::OnceCallback<void(const AuthCredentials*)> callback,
237*6777b538SAndroid Build Coastguard Worker                      std::optional<AuthCredentials>* credentials);
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker   // Sets |state_| to |new_state| and updates UMA if necessary.
240*6777b538SAndroid Build Coastguard Worker   void SetState(State new_state);
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker   // Returns true if state_ is SEND_CLOSED, CLOSE_WAIT or CLOSED.
243*6777b538SAndroid Build Coastguard Worker   bool InClosingState() const;
244*6777b538SAndroid Build Coastguard Worker 
245*6777b538SAndroid Build Coastguard Worker   // Calls WebSocketStream::WriteFrames() with the appropriate arguments
246*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState WriteFrames();
247*6777b538SAndroid Build Coastguard Worker 
248*6777b538SAndroid Build Coastguard Worker   // Callback from WebSocketStream::WriteFrames. Sends pending data or adjusts
249*6777b538SAndroid Build Coastguard Worker   // the send quota of the renderer channel as appropriate. |result| is a net
250*6777b538SAndroid Build Coastguard Worker   // error code, usually OK. If |synchronous| is true, then OnWriteDone() is
251*6777b538SAndroid Build Coastguard Worker   // being called from within the WriteFrames() loop and does not need to call
252*6777b538SAndroid Build Coastguard Worker   // WriteFrames() itself.
253*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState OnWriteDone(bool synchronous, int result);
254*6777b538SAndroid Build Coastguard Worker 
255*6777b538SAndroid Build Coastguard Worker   // Callback from WebSocketStream::ReadFrames. Handles any errors and processes
256*6777b538SAndroid Build Coastguard Worker   // the returned chunks appropriately to their type. |result| is a net error
257*6777b538SAndroid Build Coastguard Worker   // code. If |synchronous| is true, then OnReadDone() is being called from
258*6777b538SAndroid Build Coastguard Worker   // within the ReadFrames() loop and does not need to call ReadFrames() itself.
259*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState OnReadDone(bool synchronous, int result);
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker   // Handles a single frame that the object has received enough of to process.
262*6777b538SAndroid Build Coastguard Worker   // May call |event_interface_| methods, send responses to the server, and
263*6777b538SAndroid Build Coastguard Worker   // change the value of |state_|.
264*6777b538SAndroid Build Coastguard Worker   //
265*6777b538SAndroid Build Coastguard Worker   // This method performs sanity checks on the frame that are needed regardless
266*6777b538SAndroid Build Coastguard Worker   // of the current state. Then, calls the HandleFrameByState() method below
267*6777b538SAndroid Build Coastguard Worker   // which performs the appropriate action(s) depending on the current state.
268*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState HandleFrame(std::unique_ptr<WebSocketFrame> frame);
269*6777b538SAndroid Build Coastguard Worker 
270*6777b538SAndroid Build Coastguard Worker   // Handles a single frame depending on the current state. It's used by the
271*6777b538SAndroid Build Coastguard Worker   // HandleFrame() method.
272*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState HandleFrameByState(
273*6777b538SAndroid Build Coastguard Worker       const WebSocketFrameHeader::OpCode opcode,
274*6777b538SAndroid Build Coastguard Worker       bool final,
275*6777b538SAndroid Build Coastguard Worker       base::span<const char> payload);
276*6777b538SAndroid Build Coastguard Worker 
277*6777b538SAndroid Build Coastguard Worker   // Forwards a received data frame to the renderer, if connected. If
278*6777b538SAndroid Build Coastguard Worker   // |expecting_continuation| is not equal to |expecting_to_read_continuation_|,
279*6777b538SAndroid Build Coastguard Worker   // will fail the channel. Also checks the UTF-8 validity of text frames.
280*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState HandleDataFrame(
281*6777b538SAndroid Build Coastguard Worker       WebSocketFrameHeader::OpCode opcode,
282*6777b538SAndroid Build Coastguard Worker       bool final,
283*6777b538SAndroid Build Coastguard Worker       base::span<const char> payload);
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker   // Handles an incoming close frame with |code| and |reason|.
286*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState HandleCloseFrame(uint16_t code,
287*6777b538SAndroid Build Coastguard Worker                                               const std::string& reason);
288*6777b538SAndroid Build Coastguard Worker 
289*6777b538SAndroid Build Coastguard Worker   // Responds to a closing handshake initiated by the server.
290*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState RespondToClosingHandshake();
291*6777b538SAndroid Build Coastguard Worker 
292*6777b538SAndroid Build Coastguard Worker   // Low-level method to send a single frame. Used for both data and control
293*6777b538SAndroid Build Coastguard Worker   // frames. Either sends the frame immediately or buffers it to be scheduled
294*6777b538SAndroid Build Coastguard Worker   // when the current write finishes. |fin| and |op_code| are defined as for
295*6777b538SAndroid Build Coastguard Worker   // SendFrame() above, except that |op_code| may also be a control frame
296*6777b538SAndroid Build Coastguard Worker   // opcode.
297*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState SendFrameInternal(
298*6777b538SAndroid Build Coastguard Worker       bool fin,
299*6777b538SAndroid Build Coastguard Worker       WebSocketFrameHeader::OpCode op_code,
300*6777b538SAndroid Build Coastguard Worker       scoped_refptr<IOBuffer> buffer,
301*6777b538SAndroid Build Coastguard Worker       uint64_t buffer_size);
302*6777b538SAndroid Build Coastguard Worker 
303*6777b538SAndroid Build Coastguard Worker   // Performs the "Fail the WebSocket Connection" operation as defined in
304*6777b538SAndroid Build Coastguard Worker   // RFC6455. A NotifyFailure message is sent to the renderer with |message|.
305*6777b538SAndroid Build Coastguard Worker   // The renderer will log the message to the console but not expose it to
306*6777b538SAndroid Build Coastguard Worker   // Javascript. Javascript will see a Close code of AbnormalClosure (1006) with
307*6777b538SAndroid Build Coastguard Worker   // an empty reason string. If state_ is CONNECTED then a Close message is sent
308*6777b538SAndroid Build Coastguard Worker   // to the remote host containing the supplied |code| and |reason|. If the
309*6777b538SAndroid Build Coastguard Worker   // stream is open, closes it and sets state_ to CLOSED. This function deletes
310*6777b538SAndroid Build Coastguard Worker   // |this|.
311*6777b538SAndroid Build Coastguard Worker   void FailChannel(const std::string& message,
312*6777b538SAndroid Build Coastguard Worker                    uint16_t code,
313*6777b538SAndroid Build Coastguard Worker                    const std::string& reason);
314*6777b538SAndroid Build Coastguard Worker 
315*6777b538SAndroid Build Coastguard Worker   // Sends a Close frame to Start the WebSocket Closing Handshake, or to respond
316*6777b538SAndroid Build Coastguard Worker   // to a Close frame from the server. As a special case, setting |code| to
317*6777b538SAndroid Build Coastguard Worker   // kWebSocketErrorNoStatusReceived will create a Close frame with no payload;
318*6777b538SAndroid Build Coastguard Worker   // this is symmetric with the behaviour of ParseClose.
319*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] ChannelState SendClose(uint16_t code,
320*6777b538SAndroid Build Coastguard Worker                                        const std::string& reason);
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker   // Parses a Close frame payload. If no status code is supplied, then |code| is
323*6777b538SAndroid Build Coastguard Worker   // set to 1005 (No status code) with empty |reason|. If the reason text is not
324*6777b538SAndroid Build Coastguard Worker   // valid UTF-8, then |reason| is set to an empty string. If the payload size
325*6777b538SAndroid Build Coastguard Worker   // is 1, or the supplied code is not permitted to be sent over the network,
326*6777b538SAndroid Build Coastguard Worker   // then false is returned and |message| is set to an appropriate console
327*6777b538SAndroid Build Coastguard Worker   // message.
328*6777b538SAndroid Build Coastguard Worker   bool ParseClose(base::span<const char> payload,
329*6777b538SAndroid Build Coastguard Worker                   uint16_t* code,
330*6777b538SAndroid Build Coastguard Worker                   std::string* reason,
331*6777b538SAndroid Build Coastguard Worker                   std::string* message);
332*6777b538SAndroid Build Coastguard Worker 
333*6777b538SAndroid Build Coastguard Worker   // Drop this channel.
334*6777b538SAndroid Build Coastguard Worker   // If there are pending opening handshake notifications, notify them
335*6777b538SAndroid Build Coastguard Worker   // before dropping. This function deletes |this|.
336*6777b538SAndroid Build Coastguard Worker   void DoDropChannel(bool was_clean, uint16_t code, const std::string& reason);
337*6777b538SAndroid Build Coastguard Worker 
338*6777b538SAndroid Build Coastguard Worker   // Called if the closing handshake times out. Closes the connection and
339*6777b538SAndroid Build Coastguard Worker   // informs the |event_interface_| if appropriate.
340*6777b538SAndroid Build Coastguard Worker   void CloseTimeout();
341*6777b538SAndroid Build Coastguard Worker 
342*6777b538SAndroid Build Coastguard Worker   // The URL of the remote server.
343*6777b538SAndroid Build Coastguard Worker   GURL socket_url_;
344*6777b538SAndroid Build Coastguard Worker 
345*6777b538SAndroid Build Coastguard Worker   // The object receiving events.
346*6777b538SAndroid Build Coastguard Worker   const std::unique_ptr<WebSocketEventInterface> event_interface_;
347*6777b538SAndroid Build Coastguard Worker 
348*6777b538SAndroid Build Coastguard Worker   // The URLRequestContext to pass to the WebSocketStream creator.
349*6777b538SAndroid Build Coastguard Worker   const raw_ptr<URLRequestContext> url_request_context_;
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker   // The WebSocketStream on which to send and receive data.
352*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<WebSocketStream> stream_;
353*6777b538SAndroid Build Coastguard Worker 
354*6777b538SAndroid Build Coastguard Worker   // A data structure containing a vector of frames to be sent and the total
355*6777b538SAndroid Build Coastguard Worker   // number of bytes contained in the vector.
356*6777b538SAndroid Build Coastguard Worker   class SendBuffer;
357*6777b538SAndroid Build Coastguard Worker 
358*6777b538SAndroid Build Coastguard Worker   // Data that is currently pending write, or NULL if no write is pending.
359*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SendBuffer> data_being_sent_;
360*6777b538SAndroid Build Coastguard Worker   // Data that is queued up to write after the current write completes.
361*6777b538SAndroid Build Coastguard Worker   // Only non-NULL when such data actually exists.
362*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<SendBuffer> data_to_send_next_;
363*6777b538SAndroid Build Coastguard Worker 
364*6777b538SAndroid Build Coastguard Worker   // Destination for the current call to WebSocketStream::ReadFrames
365*6777b538SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<WebSocketFrame>> read_frames_;
366*6777b538SAndroid Build Coastguard Worker 
367*6777b538SAndroid Build Coastguard Worker   // Handle to an in-progress WebSocketStream creation request. Only non-NULL
368*6777b538SAndroid Build Coastguard Worker   // during the connection process.
369*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<WebSocketStreamRequest> stream_request_;
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker   // Timer for the closing handshake.
372*6777b538SAndroid Build Coastguard Worker   base::OneShotTimer close_timer_;
373*6777b538SAndroid Build Coastguard Worker 
374*6777b538SAndroid Build Coastguard Worker   // Timeout for the closing handshake.
375*6777b538SAndroid Build Coastguard Worker   base::TimeDelta closing_handshake_timeout_;
376*6777b538SAndroid Build Coastguard Worker 
377*6777b538SAndroid Build Coastguard Worker   // Timeout for the underlying connection close after completion of closing
378*6777b538SAndroid Build Coastguard Worker   // handshake.
379*6777b538SAndroid Build Coastguard Worker   base::TimeDelta underlying_connection_close_timeout_;
380*6777b538SAndroid Build Coastguard Worker 
381*6777b538SAndroid Build Coastguard Worker   // Storage for the status code and reason from the time the Close frame
382*6777b538SAndroid Build Coastguard Worker   // arrives until the connection is closed and they are passed to
383*6777b538SAndroid Build Coastguard Worker   // OnDropChannel().
384*6777b538SAndroid Build Coastguard Worker   bool has_received_close_frame_ = false;
385*6777b538SAndroid Build Coastguard Worker   uint16_t received_close_code_ = 0;
386*6777b538SAndroid Build Coastguard Worker   std::string received_close_reason_;
387*6777b538SAndroid Build Coastguard Worker 
388*6777b538SAndroid Build Coastguard Worker   // The current state of the channel. Mainly used for sanity checking, but also
389*6777b538SAndroid Build Coastguard Worker   // used to track the close state.
390*6777b538SAndroid Build Coastguard Worker   State state_ = FRESHLY_CONSTRUCTED;
391*6777b538SAndroid Build Coastguard Worker 
392*6777b538SAndroid Build Coastguard Worker   // UTF-8 validator for outgoing Text messages.
393*6777b538SAndroid Build Coastguard Worker   base::StreamingUtf8Validator outgoing_utf8_validator_;
394*6777b538SAndroid Build Coastguard Worker   bool sending_text_message_ = false;
395*6777b538SAndroid Build Coastguard Worker 
396*6777b538SAndroid Build Coastguard Worker   // UTF-8 validator for incoming Text messages.
397*6777b538SAndroid Build Coastguard Worker   base::StreamingUtf8Validator incoming_utf8_validator_;
398*6777b538SAndroid Build Coastguard Worker   bool receiving_text_message_ = false;
399*6777b538SAndroid Build Coastguard Worker 
400*6777b538SAndroid Build Coastguard Worker   // True if we are in the middle of receiving a message.
401*6777b538SAndroid Build Coastguard Worker   bool expecting_to_handle_continuation_ = false;
402*6777b538SAndroid Build Coastguard Worker 
403*6777b538SAndroid Build Coastguard Worker   // True if we have already sent the type (Text or Binary) of the current
404*6777b538SAndroid Build Coastguard Worker   // message to the renderer. This can be false if the message is empty so far.
405*6777b538SAndroid Build Coastguard Worker   bool initial_frame_forwarded_ = false;
406*6777b538SAndroid Build Coastguard Worker 
407*6777b538SAndroid Build Coastguard Worker   // True if we're waiting for OnReadDone() callback.
408*6777b538SAndroid Build Coastguard Worker   bool is_reading_ = false;
409*6777b538SAndroid Build Coastguard Worker };
410*6777b538SAndroid Build Coastguard Worker 
411*6777b538SAndroid Build Coastguard Worker }  // namespace net
412*6777b538SAndroid Build Coastguard Worker 
413*6777b538SAndroid Build Coastguard Worker #endif  // NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
414