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_BASIC_STREAM_H_ 6 #define NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 #include "base/containers/queue.h" 16 #include "base/containers/span.h" 17 #include "base/memory/scoped_refptr.h" 18 #include "base/time/time.h" 19 #include "net/base/completion_once_callback.h" 20 #include "net/base/net_export.h" 21 #include "net/log/net_log_with_source.h" 22 #include "net/traffic_annotation/network_traffic_annotation.h" 23 #include "net/websockets/websocket_frame.h" 24 #include "net/websockets/websocket_frame_parser.h" 25 #include "net/websockets/websocket_stream.h" 26 27 namespace base { 28 class TimeTicks; 29 } // namespace base 30 31 namespace net { 32 33 class ClientSocketHandle; 34 class DrainableIOBuffer; 35 class GrowableIOBuffer; 36 class IOBuffer; 37 class IOBufferWithSize; 38 struct WebSocketFrame; 39 struct WebSocketFrameChunk; 40 struct NetworkTrafficAnnotationTag; 41 42 // Implementation of WebSocketStream for non-multiplexed ws:// connections (or 43 // the physical side of a multiplexed ws:// connection). 44 // 45 // Please update the traffic annotations in the websocket_basic_stream.cc and 46 // websocket_stream.cc if the class is used for any communication with Google. 47 // In such a case, annotation should be passed from the callers to this class 48 // and a local annotation can not be used anymore. 49 class NET_EXPORT_PRIVATE WebSocketBasicStream final : public WebSocketStream { 50 public: 51 typedef WebSocketMaskingKey (*WebSocketMaskingKeyGeneratorFunction)(); 52 53 enum class BufferSize : uint8_t { 54 kSmall, 55 kLarge, 56 }; 57 58 // A class that calculates whether the associated WebSocketBasicStream 59 // should use a small buffer or large buffer, given the timing information 60 // or Read calls. This class is public for testing. 61 class NET_EXPORT_PRIVATE BufferSizeManager final { 62 public: 63 BufferSizeManager(); 64 BufferSizeManager(const BufferSizeManager&) = delete; 65 BufferSizeManager& operator=(const BufferSizeManager&) = delete; 66 ~BufferSizeManager(); 67 68 // Called when the associated WebSocketBasicStream starts reading data 69 // into a buffer. 70 void OnRead(base::TimeTicks now); 71 72 // Called when the Read operation completes. `size` must be positive. 73 void OnReadComplete(base::TimeTicks now, int size); 74 75 // Returns the appropriate buffer size the associated WebSocketBasicStream 76 // should use. buffer_size()77 BufferSize buffer_size() const { return buffer_size_; } 78 79 // Set the rolling average window for tests. set_window_for_test(size_t size)80 void set_window_for_test(size_t size) { rolling_average_window_ = size; } 81 82 private: 83 // This keeps the best read buffer size. 84 BufferSize buffer_size_ = BufferSize::kSmall; 85 86 // The number of results to calculate the throughput. This is a variable so 87 // that unittests can set other values. 88 size_t rolling_average_window_ = 100; 89 90 // This keeps the timestamps to calculate the throughput. 91 base::queue<base::TimeTicks> read_start_timestamps_; 92 93 // The sum of the last few read size. 94 int rolling_byte_total_ = 0; 95 96 // This keeps the read size. 97 base::queue<int> recent_read_sizes_; 98 }; 99 100 // Adapter that allows WebSocketBasicStream to use 101 // either a TCP/IP or TLS socket, or an HTTP/2 stream. 102 class Adapter { 103 public: 104 virtual ~Adapter() = default; 105 virtual int Read(IOBuffer* buf, 106 int buf_len, 107 CompletionOnceCallback callback) = 0; 108 virtual int Write( 109 IOBuffer* buf, 110 int buf_len, 111 CompletionOnceCallback callback, 112 const NetworkTrafficAnnotationTag& traffic_annotation) = 0; 113 virtual void Disconnect() = 0; 114 virtual bool is_initialized() const = 0; 115 }; 116 117 // This class should not normally be constructed directly; see 118 // WebSocketStream::CreateAndConnectStream() and 119 // WebSocketBasicHandshakeStream::Upgrade(). 120 WebSocketBasicStream(std::unique_ptr<Adapter> connection, 121 const scoped_refptr<GrowableIOBuffer>& http_read_buffer, 122 const std::string& sub_protocol, 123 const std::string& extensions, 124 const NetLogWithSource& net_log); 125 126 // The destructor has to make sure the connection is closed when we finish so 127 // that it does not get returned to the pool. 128 ~WebSocketBasicStream() override; 129 130 // WebSocketStream implementation. 131 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames, 132 CompletionOnceCallback callback) override; 133 134 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames, 135 CompletionOnceCallback callback) override; 136 137 void Close() override; 138 139 std::string GetSubProtocol() const override; 140 141 std::string GetExtensions() const override; 142 143 const NetLogWithSource& GetNetLogWithSource() const override; 144 145 //////////////////////////////////////////////////////////////////////////// 146 // Methods for testing only. 147 148 static std::unique_ptr<WebSocketBasicStream> 149 CreateWebSocketBasicStreamForTesting( 150 std::unique_ptr<ClientSocketHandle> connection, 151 const scoped_refptr<GrowableIOBuffer>& http_read_buffer, 152 const std::string& sub_protocol, 153 const std::string& extensions, 154 const NetLogWithSource& net_log, 155 WebSocketMaskingKeyGeneratorFunction key_generator_function); 156 157 private: 158 // Reads until socket read returns asynchronously or returns error. 159 // If returns ERR_IO_PENDING, then |read_callback_| will be called with result 160 // later. 161 int ReadEverything(std::vector<std::unique_ptr<WebSocketFrame>>* frames); 162 163 // Called when a read completes. Parses the result, tries to read more. 164 // Might call |read_callback_|. 165 void OnReadComplete(std::vector<std::unique_ptr<WebSocketFrame>>* frames, 166 int result); 167 168 // Writes until |buffer| is fully drained (in which case returns OK) or a 169 // socket write returns asynchronously or returns an error. If returns 170 // ERR_IO_PENDING, then |write_callback_| will be called with result later. 171 int WriteEverything(const scoped_refptr<DrainableIOBuffer>& buffer); 172 173 // Called when a write completes. Tries to write more. 174 // Might call |write_callback_|. 175 void OnWriteComplete(const scoped_refptr<DrainableIOBuffer>& buffer, 176 int result); 177 178 // Attempts to parse the output of a read as WebSocket frames. On success, 179 // returns OK and places the frame(s) in |frames|. 180 int HandleReadResult(int result, 181 std::vector<std::unique_ptr<WebSocketFrame>>* frames); 182 183 // Converts the chunks in |frame_chunks| into frames and writes them to 184 // |frames|. |frame_chunks| is destroyed in the process. Returns 185 // ERR_WS_PROTOCOL_ERROR if an invalid chunk was found. If one or more frames 186 // was added to |frames|, then returns OK, otherwise returns ERR_IO_PENDING. 187 int ConvertChunksToFrames( 188 std::vector<std::unique_ptr<WebSocketFrameChunk>>* frame_chunks, 189 std::vector<std::unique_ptr<WebSocketFrame>>* frames); 190 191 // Converts a |chunk| to a |frame|. |*frame| should be NULL on entry to this 192 // method. If |chunk| is an incomplete control frame, or an empty middle 193 // frame, then |*frame| may still be NULL on exit. If an invalid control frame 194 // is found, returns ERR_WS_PROTOCOL_ERROR and the stream is no longer 195 // usable. Otherwise returns OK (even if frame is still NULL). 196 int ConvertChunkToFrame(std::unique_ptr<WebSocketFrameChunk> chunk, 197 std::unique_ptr<WebSocketFrame>* frame); 198 199 // Creates a frame based on the value of |is_final_chunk|, |data| and 200 // |current_frame_header_|. Clears |current_frame_header_| if |is_final_chunk| 201 // is true. |data| may be NULL if the frame has an empty payload. A frame in 202 // the middle of a message with no data is not useful; in this case the 203 // returned frame will be NULL. Otherwise, |current_frame_header_->opcode| is 204 // set to Continuation after use if it was Text or Binary, in accordance with 205 // WebSocket RFC6455 section 5.4. 206 std::unique_ptr<WebSocketFrame> CreateFrame(bool is_final_chunk, 207 base::span<const char> data); 208 209 // Adds |data_buffer| to the end of |incomplete_control_frame_body_|, applying 210 // bounds checks. 211 void AddToIncompleteControlFrameBody(base::span<const char> data); 212 213 // Storage for pending reads. 214 scoped_refptr<IOBufferWithSize> read_buffer_; 215 216 // The best read buffer size for the current throughput. 217 size_t target_read_buffer_size_; 218 219 // The connection, wrapped in a ClientSocketHandle so that we can prevent it 220 // from being returned to the pool. 221 std::unique_ptr<Adapter> connection_; 222 223 // Frame header for the frame currently being received. Only non-NULL while we 224 // are processing the frame. If the frame arrives in multiple chunks, it can 225 // remain non-NULL until additional chunks arrive. If the header of the frame 226 // was invalid, this is set to NULL, the channel is failed, and subsequent 227 // chunks of the same frame will be ignored. 228 std::unique_ptr<WebSocketFrameHeader> current_frame_header_; 229 230 // Although it should rarely happen in practice, a control frame can arrive 231 // broken into chunks. This variable provides storage for a partial control 232 // frame until the rest arrives. It will be empty the rest of the time. 233 std::vector<char> incomplete_control_frame_body_; 234 // Storage for payload of combined (see |incomplete_control_frame_body_|) 235 // control frame. 236 std::vector<char> complete_control_frame_body_; 237 238 // Only used during handshake. Some data may be left in this buffer after the 239 // handshake, in which case it will be picked up during the first call to 240 // ReadFrames(). The type is GrowableIOBuffer for compatibility with 241 // net::HttpStreamParser, which is used to parse the handshake. 242 scoped_refptr<GrowableIOBuffer> http_read_buffer_; 243 // Flag to keep above buffer until next ReadFrames() after decoding. 244 bool is_http_read_buffer_decoded_ = false; 245 246 // This keeps the current parse state (including any incomplete headers) and 247 // parses frames. 248 WebSocketFrameParser parser_; 249 250 // The negotated sub-protocol, or empty for none. 251 const std::string sub_protocol_; 252 253 // The extensions negotiated with the remote server. 254 const std::string extensions_; 255 256 NetLogWithSource net_log_; 257 258 // This is used for adaptive read buffer size. 259 BufferSizeManager buffer_size_manager_; 260 261 // This keeps the current read buffer size. 262 BufferSize buffer_size_ = buffer_size_manager_.buffer_size(); 263 264 // This can be overridden in tests to make the output deterministic. We don't 265 // use a Callback here because a function pointer is faster and good enough 266 // for our purposes. 267 WebSocketMaskingKeyGeneratorFunction generate_websocket_masking_key_; 268 269 // User callback saved for asynchronous writes and reads. 270 CompletionOnceCallback write_callback_; 271 CompletionOnceCallback read_callback_; 272 }; 273 274 } // namespace net 275 276 #endif // NET_WEBSOCKETS_WEBSOCKET_BASIC_STREAM_H_ 277