xref: /aosp_15_r20/external/cronet/net/websockets/websocket_frame_parser.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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_FRAME_PARSER_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_WEBSOCKETS_WEBSOCKET_FRAME_PARSER_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 <vector>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_errors.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_frame.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace net {
20*6777b538SAndroid Build Coastguard Worker struct WebSocketFrameChunk;
21*6777b538SAndroid Build Coastguard Worker struct WebSocketFrameHeader;
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker // Parses WebSocket frames from byte stream.
24*6777b538SAndroid Build Coastguard Worker //
25*6777b538SAndroid Build Coastguard Worker // Specification of WebSocket frame format is available at
26*6777b538SAndroid Build Coastguard Worker // <http://tools.ietf.org/html/rfc6455#section-5>.
27*6777b538SAndroid Build Coastguard Worker // This class does *NOT* unmask frame payload.
28*6777b538SAndroid Build Coastguard Worker class NET_EXPORT WebSocketFrameParser {
29*6777b538SAndroid Build Coastguard Worker  public:
30*6777b538SAndroid Build Coastguard Worker   WebSocketFrameParser();
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker   WebSocketFrameParser(const WebSocketFrameParser&) = delete;
33*6777b538SAndroid Build Coastguard Worker   WebSocketFrameParser& operator=(const WebSocketFrameParser&) = delete;
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker   ~WebSocketFrameParser();
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker   // Decodes the given byte stream and stores parsed WebSocket frames in
38*6777b538SAndroid Build Coastguard Worker   // |frame_chunks|.
39*6777b538SAndroid Build Coastguard Worker   // Each WebSocketFrameChunk's payload is a subspan of [data, data + length).
40*6777b538SAndroid Build Coastguard Worker   // Thus callers must take care of its lifecycle.
41*6777b538SAndroid Build Coastguard Worker   //
42*6777b538SAndroid Build Coastguard Worker   // If the parser encounters invalid payload length format, Decode() fails
43*6777b538SAndroid Build Coastguard Worker   // and returns false. Once Decode() has failed, the parser refuses to decode
44*6777b538SAndroid Build Coastguard Worker   // any more data and future invocations of Decode() will simply return false.
45*6777b538SAndroid Build Coastguard Worker   //
46*6777b538SAndroid Build Coastguard Worker   // Payload data of parsed WebSocket frames may be incomplete; see comments in
47*6777b538SAndroid Build Coastguard Worker   // websocket_frame.h for more details.
48*6777b538SAndroid Build Coastguard Worker   bool Decode(const char* data,
49*6777b538SAndroid Build Coastguard Worker               size_t length,
50*6777b538SAndroid Build Coastguard Worker               std::vector<std::unique_ptr<WebSocketFrameChunk>>* frame_chunks);
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker   // Returns kWebSocketNormalClosure if the parser has not failed to decode
53*6777b538SAndroid Build Coastguard Worker   // WebSocket frames. Otherwise returns WebSocketError which is defined in
54*6777b538SAndroid Build Coastguard Worker   // websocket_errors.h. We can convert net::WebSocketError to net::Error by
55*6777b538SAndroid Build Coastguard Worker   // using WebSocketErrorToNetError().
websocket_error()56*6777b538SAndroid Build Coastguard Worker   WebSocketError websocket_error() const { return websocket_error_; }
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker  private:
59*6777b538SAndroid Build Coastguard Worker   // Tries to decode a frame header from |data|.
60*6777b538SAndroid Build Coastguard Worker   // If successful, this function updates
61*6777b538SAndroid Build Coastguard Worker   // |current_frame_header_|, and |masking_key_| (if available) and returns
62*6777b538SAndroid Build Coastguard Worker   // the number of consumed bytes in |data|.
63*6777b538SAndroid Build Coastguard Worker   // If there is not enough data in the remaining buffer to parse a frame
64*6777b538SAndroid Build Coastguard Worker   // header, this function returns 0 without doing anything.
65*6777b538SAndroid Build Coastguard Worker   // This function may update |websocket_error_| if it observes a corrupt frame.
66*6777b538SAndroid Build Coastguard Worker   size_t DecodeFrameHeader(base::span<const uint8_t> data);
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker   // Decodes frame payload and creates a WebSocketFrameChunk object.
69*6777b538SAndroid Build Coastguard Worker   // This function updates |frame_offset_| after
70*6777b538SAndroid Build Coastguard Worker   // parsing. This function returns a frame object even if no payload data is
71*6777b538SAndroid Build Coastguard Worker   // available at this moment, so the receiver could make use of frame header
72*6777b538SAndroid Build Coastguard Worker   // information. If the end of frame is reached, this function clears
73*6777b538SAndroid Build Coastguard Worker   // |current_frame_header_|, |frame_offset_| and |masking_key_|.
74*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<WebSocketFrameChunk> DecodeFramePayload(
75*6777b538SAndroid Build Coastguard Worker       bool first_chunk,
76*6777b538SAndroid Build Coastguard Worker       base::span<const char>* data);
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker   // Internal buffer to store the data to parse header.
79*6777b538SAndroid Build Coastguard Worker   std::vector<char> incomplete_header_buffer_;
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   // Frame header and masking key of the current frame.
82*6777b538SAndroid Build Coastguard Worker   // |masking_key_| is filled with zeros if the current frame is not masked.
83*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<WebSocketFrameHeader> current_frame_header_;
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker   // Amount of payload data read so far for the current frame.
86*6777b538SAndroid Build Coastguard Worker   uint64_t frame_offset_ = 0;
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker   WebSocketError websocket_error_ = kWebSocketNormalClosure;
89*6777b538SAndroid Build Coastguard Worker };
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker }  // namespace net
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker #endif  // NET_WEBSOCKETS_WEBSOCKET_FRAME_PARSER_H_
94