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