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 // Tests for WebSocketBasicStream. Note that we do not attempt to verify that
6 // frame parsing itself functions correctly, as that is covered by the
7 // WebSocketFrameParser tests.
8
9 #include "net/websockets/websocket_basic_stream.h"
10
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <string.h> // for memcpy() and memset().
14
15 #include <iterator>
16 #include <utility>
17
18 #include "base/big_endian.h"
19 #include "base/containers/span.h"
20 #include "base/strings/string_piece.h"
21 #include "base/time/time.h"
22 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/network_anonymization_key.h"
25 #include "net/base/privacy_mode.h"
26 #include "net/base/request_priority.h"
27 #include "net/base/test_completion_callback.h"
28 #include "net/dns/public/secure_dns_policy.h"
29 #include "net/socket/client_socket_handle.h"
30 #include "net/socket/client_socket_pool.h"
31 #include "net/socket/connect_job.h"
32 #include "net/socket/socket_tag.h"
33 #include "net/socket/socket_test_util.h"
34 #include "net/test/gtest_util.h"
35 #include "net/test/test_with_task_environment.h"
36 #include "net/traffic_annotation/network_traffic_annotation.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39 #include "third_party/abseil-cpp/absl/types/optional.h"
40 #include "url/scheme_host_port.h"
41 #include "url/url_constants.h"
42
43 using net::test::IsError;
44 using net::test::IsOk;
45
46 namespace net {
47 namespace {
48
49 #define WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(name, value) \
50 const char k##name[] = value; \
51 const size_t k##name##Size = std::size(k##name) - 1
52
53 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(SampleFrame, "\x81\x06Sample");
54 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
55 PartialLargeFrame,
56 "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF"
57 "chromiunum ad pasco per loca insanis pullum manducat frumenti");
58 const size_t kLargeFrameHeaderSize = 10;
59 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MultipleFrames,
60 "\x81\x01X\x81\x01Y\x81\x01Z");
61 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFirstFrame, "\x01\x00");
62 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyMiddleFrame, "\x00\x00");
63 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalTextFrame, "\x81\x00");
64 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalContinuationFrame,
65 "\x80\x00");
66 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(ValidPong, "\x8A\x00");
67 // This frame encodes a payload length of 7 in two bytes, which is always
68 // invalid.
69 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(InvalidFrame,
70 "\x81\x7E\x00\x07Invalid");
71 // Control frames must have the FIN bit set. This one does not.
72 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(PingFrameWithoutFin, "\x09\x00");
73 // Control frames must have a payload of 125 bytes or less. This one has
74 // a payload of 126 bytes.
75 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
76 126BytePong,
77 "\x8a\x7e\x00\x7eZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
78 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
79 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(CloseFrame,
80 "\x88\x09\x03\xe8occludo");
81 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(WriteFrame,
82 "\x81\x85\x00\x00\x00\x00Write");
83 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MaskedEmptyPong,
84 "\x8A\x80\x00\x00\x00\x00");
85 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}};
86 const WebSocketMaskingKey kNonNulMaskingKey = {
87 {'\x0d', '\x1b', '\x06', '\x17'}};
88
89 // A masking key generator function which generates the identity mask,
90 // ie. "\0\0\0\0".
GenerateNulMaskingKey()91 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
92
93 // A masking key generation function which generates a fixed masking key with no
94 // nul characters.
GenerateNonNulMaskingKey()95 WebSocketMaskingKey GenerateNonNulMaskingKey() { return kNonNulMaskingKey; }
96
97 // A subclass of StaticSocketDataProvider modified to require that all data
98 // expected to be read or written actually is.
99 class StrictStaticSocketDataProvider : public StaticSocketDataProvider {
100 public:
StrictStaticSocketDataProvider(base::span<const MockRead> reads,base::span<const MockWrite> writes,bool strict_mode)101 StrictStaticSocketDataProvider(base::span<const MockRead> reads,
102 base::span<const MockWrite> writes,
103 bool strict_mode)
104 : StaticSocketDataProvider(reads, writes), strict_mode_(strict_mode) {}
105
~StrictStaticSocketDataProvider()106 ~StrictStaticSocketDataProvider() override {
107 if (strict_mode_) {
108 EXPECT_EQ(read_count(), read_index());
109 EXPECT_EQ(write_count(), write_index());
110 }
111 }
112
113 private:
114 const bool strict_mode_;
115 };
116
117 // A fixture for tests which only perform normal socket operations.
118 class WebSocketBasicStreamSocketTest : public TestWithTaskEnvironment {
119 protected:
WebSocketBasicStreamSocketTest()120 WebSocketBasicStreamSocketTest()
121 : common_connect_job_params_(
122 &factory_,
123 /*host_resolver=*/nullptr,
124 /*http_auth_cache=*/nullptr,
125 /*http_auth_handler_factory=*/nullptr,
126 /*spdy_session_pool=*/nullptr,
127 /*quic_supported_versions=*/nullptr,
128 /*quic_stream_factory=*/nullptr,
129 /*proxy_delegate=*/nullptr,
130 /*http_user_agent_settings=*/nullptr,
131 /*ssl_client_context=*/nullptr,
132 /*socket_performance_watcher_factory=*/nullptr,
133 /*network_quality_estimator=*/nullptr,
134 /*net_log=*/nullptr,
135 /*websocket_endpoint_lock_manager=*/nullptr,
136 /*http_server_properties*/ nullptr,
137 /*alpn_protos=*/nullptr,
138 /*application_settings=*/nullptr,
139 /*ignore_certificate_errors=*/nullptr),
140 pool_(1, 1, &common_connect_job_params_),
141 generator_(&GenerateNulMaskingKey) {}
142
~WebSocketBasicStreamSocketTest()143 ~WebSocketBasicStreamSocketTest() override {
144 // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
145 // should be destroyed first.
146 stream_.reset();
147 }
148
MakeTransportSocket(base::span<const MockRead> reads,base::span<const MockWrite> writes)149 std::unique_ptr<ClientSocketHandle> MakeTransportSocket(
150 base::span<const MockRead> reads,
151 base::span<const MockWrite> writes) {
152 socket_data_ = std::make_unique<StrictStaticSocketDataProvider>(
153 reads, writes, expect_all_io_to_complete_);
154 socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
155 factory_.AddSocketDataProvider(socket_data_.get());
156
157 auto transport_socket = std::make_unique<ClientSocketHandle>();
158 scoped_refptr<ClientSocketPool::SocketParams> null_params;
159 ClientSocketPool::GroupId group_id(
160 url::SchemeHostPort(url::kHttpScheme, "a", 80),
161 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
162 SecureDnsPolicy::kAllow);
163 transport_socket->Init(
164 group_id, null_params, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
165 SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
166 CompletionOnceCallback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
167 NetLogWithSource());
168 return transport_socket;
169 }
170
SetHttpReadBuffer(const char * data,size_t size)171 void SetHttpReadBuffer(const char* data, size_t size) {
172 http_read_buffer_ = base::MakeRefCounted<GrowableIOBuffer>();
173 http_read_buffer_->SetCapacity(size);
174 memcpy(http_read_buffer_->data(), data, size);
175 http_read_buffer_->set_offset(size);
176 }
177
CreateStream(base::span<const MockRead> reads,base::span<const MockWrite> writes)178 void CreateStream(base::span<const MockRead> reads,
179 base::span<const MockWrite> writes) {
180 stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
181 MakeTransportSocket(reads, writes), http_read_buffer_, sub_protocol_,
182 extensions_, net_log_, generator_);
183 }
184
185 std::unique_ptr<SocketDataProvider> socket_data_;
186 MockClientSocketFactory factory_;
187 const CommonConnectJobParams common_connect_job_params_;
188 MockTransportClientSocketPool pool_;
189 std::vector<std::unique_ptr<WebSocketFrame>> frames_;
190 TestCompletionCallback cb_;
191 scoped_refptr<GrowableIOBuffer> http_read_buffer_;
192 std::string sub_protocol_;
193 std::string extensions_;
194 NetLogWithSource net_log_;
195 WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_;
196 bool expect_all_io_to_complete_ = true;
197 std::unique_ptr<WebSocketBasicStream> stream_;
198 };
199
200 // A test fixture for the common case of tests that only perform a single read.
201 class WebSocketBasicStreamSocketSingleReadTest
202 : public WebSocketBasicStreamSocketTest {
203 protected:
CreateRead(const MockRead & read)204 void CreateRead(const MockRead& read) {
205 reads_[0] = read;
206 CreateStream(reads_, base::span<MockWrite>());
207 }
208
209 MockRead reads_[1];
210 };
211
212 // A test fixture for tests that perform chunked reads.
213 class WebSocketBasicStreamSocketChunkedReadTest
214 : public WebSocketBasicStreamSocketTest {
215 protected:
216 // Specify the behaviour if there aren't enough chunks to use all the data. If
217 // LAST_FRAME_BIG is specified, then the rest of the data will be
218 // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last
219 // frame will be no bigger than the rest of the frames (but it can be smaller,
220 // if not enough data remains).
221 enum LastFrameBehaviour {
222 LAST_FRAME_BIG,
223 LAST_FRAME_NOT_BIG
224 };
225
226 // Prepares a read from |data| of |data_size|, split into |number_of_chunks|,
227 // each of |chunk_size| (except that the last chunk may be larger or
228 // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture),
229 // and errors cannot be simulated. Once data is exhausted, further reads will
230 // return 0 (ie. connection closed).
CreateChunkedRead(IoMode mode,const char data[],size_t data_size,int chunk_size,size_t number_of_chunks,LastFrameBehaviour last_frame_behaviour)231 void CreateChunkedRead(IoMode mode,
232 const char data[],
233 size_t data_size,
234 int chunk_size,
235 size_t number_of_chunks,
236 LastFrameBehaviour last_frame_behaviour) {
237 reads_.clear();
238 const char* start = data;
239 for (size_t i = 0; i < number_of_chunks; ++i) {
240 int len = chunk_size;
241 const bool is_last_chunk = (i == number_of_chunks - 1);
242 if ((last_frame_behaviour == LAST_FRAME_BIG && is_last_chunk) ||
243 static_cast<int>(data + data_size - start) < len) {
244 len = static_cast<int>(data + data_size - start);
245 }
246 reads_.emplace_back(mode, start, len);
247 start += len;
248 }
249 CreateStream(reads_, base::span<MockWrite>());
250 }
251
252 std::vector<MockRead> reads_;
253 };
254
255 // Test fixture for write tests.
256 class WebSocketBasicStreamSocketWriteTest
257 : public WebSocketBasicStreamSocketTest {
258 protected:
259 // All write tests use the same frame, so it is easiest to create it during
260 // test creation.
SetUp()261 void SetUp() override { PrepareWriteFrame(); }
262
263 // Creates a WebSocketFrame with a wire format matching kWriteFrame and adds
264 // it to |frames_|.
PrepareWriteFrame()265 void PrepareWriteFrame() {
266 auto frame =
267 std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodeText);
268 const size_t payload_size =
269 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
270 WebSocketFrameHeader::kMaskingKeyLength);
271 auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_size);
272 frame_buffers_.push_back(buffer);
273 memcpy(buffer->data(), kWriteFrame + kWriteFrameSize - payload_size,
274 payload_size);
275 frame->payload = buffer->data();
276 WebSocketFrameHeader& header = frame->header;
277 header.final = true;
278 header.masked = true;
279 header.payload_length = payload_size;
280 frames_.push_back(std::move(frame));
281 }
282
283 // TODO(yoichio): Make this type std::vector<std::string>.
284 std::vector<scoped_refptr<IOBuffer>> frame_buffers_;
285 };
286
287 // A test fixture for tests that perform read buffer size switching.
288 class WebSocketBasicStreamSwitchTest : public WebSocketBasicStreamSocketTest {
289 protected:
290 // This is used to specify the read start/end time.
MicrosecondsFromStart(int microseconds)291 base::TimeTicks MicrosecondsFromStart(int microseconds) {
292 static const base::TimeTicks kStartPoint =
293 base::TimeTicks::UnixEpoch() + base::Seconds(60);
294 return kStartPoint + base::Microseconds(microseconds);
295 }
296
297 WebSocketBasicStream::BufferSizeManager buffer_size_manager_;
298 };
299
TEST_F(WebSocketBasicStreamSocketTest,ConstructionWorks)300 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
301 CreateStream(base::span<MockRead>(), base::span<MockWrite>());
302 }
303
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncReadWorks)304 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) {
305 CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize));
306 int result = stream_->ReadFrames(&frames_, cb_.callback());
307 EXPECT_THAT(result, IsOk());
308 ASSERT_EQ(1U, frames_.size());
309 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
310 EXPECT_TRUE(frames_[0]->header.final);
311 }
312
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncReadWorks)313 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) {
314 CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize));
315 int result = stream_->ReadFrames(&frames_, cb_.callback());
316 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
317 EXPECT_THAT(cb_.WaitForResult(), IsOk());
318 ASSERT_EQ(1U, frames_.size());
319 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
320 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the
321 // frame was really read.
322 }
323
324 // ReadFrames will not return a frame whose header has not been wholly received.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,HeaderFragmentedSync)325 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) {
326 CreateChunkedRead(
327 SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
328 int result = stream_->ReadFrames(&frames_, cb_.callback());
329 EXPECT_THAT(result, IsOk());
330 ASSERT_EQ(1U, frames_.size());
331 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
332 }
333
334 // The same behaviour applies to asynchronous reads.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,HeaderFragmentedAsync)335 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) {
336 CreateChunkedRead(
337 ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
338 int result = stream_->ReadFrames(&frames_, cb_.callback());
339 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
340 EXPECT_THAT(cb_.WaitForResult(), IsOk());
341 ASSERT_EQ(1U, frames_.size());
342 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
343 }
344
345 // If it receives an incomplete header in a synchronous call, then has to wait
346 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING.
TEST_F(WebSocketBasicStreamSocketTest,HeaderFragmentedSyncAsync)347 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
348 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
349 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
350 CreateStream(reads, base::span<MockWrite>());
351 int result = stream_->ReadFrames(&frames_, cb_.callback());
352 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
353 EXPECT_THAT(cb_.WaitForResult(), IsOk());
354 ASSERT_EQ(1U, frames_.size());
355 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
356 }
357
358 // An extended header should also return ERR_IO_PENDING if it is not completely
359 // received.
TEST_F(WebSocketBasicStreamSocketTest,FragmentedLargeHeader)360 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
361 MockRead reads[] = {
362 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
363 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
364 CreateStream(reads, base::span<MockWrite>());
365 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
366 IsError(ERR_IO_PENDING));
367 }
368
369 // A frame that does not arrive in a single read should be broken into separate
370 // frames.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,LargeFrameFirstChunk)371 TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) {
372 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize));
373 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
374 ASSERT_EQ(1U, frames_.size());
375 EXPECT_FALSE(frames_[0]->header.final);
376 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
377 static_cast<size_t>(frames_[0]->header.payload_length));
378 }
379
380 // If only the header of a data frame arrives, we should receive a frame with a
381 // zero-size payload.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,HeaderOnlyChunk)382 TEST_F(WebSocketBasicStreamSocketSingleReadTest, HeaderOnlyChunk) {
383 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize));
384
385 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
386 ASSERT_EQ(1U, frames_.size());
387 EXPECT_EQ(nullptr, frames_[0]->payload);
388 EXPECT_EQ(0U, frames_[0]->header.payload_length);
389 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
390 }
391
392 // If the header and the body of a data frame arrive seperately, we should see
393 // them as separate frames.
TEST_F(WebSocketBasicStreamSocketTest,HeaderBodySeparated)394 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) {
395 MockRead reads[] = {
396 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
397 MockRead(ASYNC,
398 kPartialLargeFrame + kLargeFrameHeaderSize,
399 kPartialLargeFrameSize - kLargeFrameHeaderSize)};
400 CreateStream(reads, base::span<MockWrite>());
401 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
402 ASSERT_EQ(1U, frames_.size());
403 EXPECT_EQ(nullptr, frames_[0]->payload);
404 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
405 frames_.clear();
406 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
407 IsError(ERR_IO_PENDING));
408 EXPECT_THAT(cb_.WaitForResult(), IsOk());
409 ASSERT_EQ(1U, frames_.size());
410 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
411 frames_[0]->header.payload_length);
412 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
413 frames_[0]->header.opcode);
414 }
415
416 // Every frame has a header with a correct payload_length field.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,LargeFrameTwoChunks)417 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) {
418 const size_t kChunkSize = 16;
419 CreateChunkedRead(ASYNC,
420 kPartialLargeFrame,
421 kPartialLargeFrameSize,
422 kChunkSize,
423 2,
424 LAST_FRAME_NOT_BIG);
425 TestCompletionCallback cb[2];
426
427 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
428 IsError(ERR_IO_PENDING));
429 EXPECT_THAT(cb[0].WaitForResult(), IsOk());
430 ASSERT_EQ(1U, frames_.size());
431 EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize,
432 frames_[0]->header.payload_length);
433
434 frames_.clear();
435 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[1].callback()),
436 IsError(ERR_IO_PENDING));
437 EXPECT_THAT(cb[1].WaitForResult(), IsOk());
438 ASSERT_EQ(1U, frames_.size());
439 EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length);
440 }
441
442 // Only the final frame of a fragmented message has |final| bit set.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,OnlyFinalChunkIsFinal)443 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) {
444 static const size_t kFirstChunkSize = 4;
445 CreateChunkedRead(ASYNC,
446 kSampleFrame,
447 kSampleFrameSize,
448 kFirstChunkSize,
449 2,
450 LAST_FRAME_BIG);
451 TestCompletionCallback cb[2];
452
453 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
454 IsError(ERR_IO_PENDING));
455 EXPECT_THAT(cb[0].WaitForResult(), IsOk());
456 ASSERT_EQ(1U, frames_.size());
457 ASSERT_FALSE(frames_[0]->header.final);
458
459 frames_.clear();
460 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[1].callback()),
461 IsError(ERR_IO_PENDING));
462 EXPECT_THAT(cb[1].WaitForResult(), IsOk());
463 ASSERT_EQ(1U, frames_.size());
464 ASSERT_TRUE(frames_[0]->header.final);
465 }
466
467 // All frames after the first have their opcode changed to Continuation.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,ContinuationOpCodeUsed)468 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ContinuationOpCodeUsed) {
469 const size_t kFirstChunkSize = 3;
470 const int kChunkCount = 3;
471 // The input data is one frame with opcode Text, which arrives in three
472 // separate chunks.
473 CreateChunkedRead(ASYNC,
474 kSampleFrame,
475 kSampleFrameSize,
476 kFirstChunkSize,
477 kChunkCount,
478 LAST_FRAME_BIG);
479 TestCompletionCallback cb[kChunkCount];
480
481 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
482 IsError(ERR_IO_PENDING));
483 EXPECT_THAT(cb[0].WaitForResult(), IsOk());
484 ASSERT_EQ(1U, frames_.size());
485 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
486
487 // This test uses a loop to verify that the opcode for every frames generated
488 // after the first is converted to Continuation.
489 for (int i = 1; i < kChunkCount; ++i) {
490 frames_.clear();
491 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[i].callback()),
492 IsError(ERR_IO_PENDING));
493 EXPECT_THAT(cb[i].WaitForResult(), IsOk());
494 ASSERT_EQ(1U, frames_.size());
495 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
496 frames_[0]->header.opcode);
497 }
498 }
499
500 // Multiple frames that arrive together should be parsed correctly.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,ThreeFramesTogether)501 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
502 CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
503
504 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
505 ASSERT_EQ(3U, frames_.size());
506 EXPECT_TRUE(frames_[0]->header.final);
507 EXPECT_TRUE(frames_[1]->header.final);
508 EXPECT_TRUE(frames_[2]->header.final);
509 }
510
511 // ERR_CONNECTION_CLOSED must be returned on close.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncClose)512 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
513 CreateRead(MockRead(SYNCHRONOUS, "", 0));
514
515 EXPECT_EQ(ERR_CONNECTION_CLOSED,
516 stream_->ReadFrames(&frames_, cb_.callback()));
517 }
518
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncClose)519 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
520 CreateRead(MockRead(ASYNC, "", 0));
521
522 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
523 IsError(ERR_IO_PENDING));
524 EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
525 }
526
527 // The result should be the same if the socket returns
528 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established
529 // connection; a Read of size 0 is the expected behaviour. The key point of this
530 // test is to confirm that ReadFrames() behaviour is identical in both cases.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncCloseWithErr)531 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) {
532 CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED));
533
534 EXPECT_EQ(ERR_CONNECTION_CLOSED,
535 stream_->ReadFrames(&frames_, cb_.callback()));
536 }
537
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncCloseWithErr)538 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
539 CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
540
541 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
542 IsError(ERR_IO_PENDING));
543 EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
544 }
545
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncErrorsPassedThrough)546 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) {
547 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
548 // WebSocketBasicStream gives no special handling to.
549 CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES));
550
551 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
552 stream_->ReadFrames(&frames_, cb_.callback()));
553 }
554
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncErrorsPassedThrough)555 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
556 CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
557
558 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
559 IsError(ERR_IO_PENDING));
560 EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_INSUFFICIENT_RESOURCES));
561 }
562
563 // If we get a frame followed by a close, we should receive them separately.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,CloseAfterFrame)564 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) {
565 // The chunk size equals the data size, so the second chunk is 0 size, closing
566 // the connection.
567 CreateChunkedRead(SYNCHRONOUS,
568 kSampleFrame,
569 kSampleFrameSize,
570 kSampleFrameSize,
571 2,
572 LAST_FRAME_NOT_BIG);
573
574 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
575 EXPECT_EQ(1U, frames_.size());
576 frames_.clear();
577 EXPECT_EQ(ERR_CONNECTION_CLOSED,
578 stream_->ReadFrames(&frames_, cb_.callback()));
579 }
580
581 // Synchronous close after an async frame header is handled by a different code
582 // path.
TEST_F(WebSocketBasicStreamSocketTest,AsyncCloseAfterIncompleteHeader)583 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
584 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
585 MockRead(SYNCHRONOUS, "", 0)};
586 CreateStream(reads, base::span<MockWrite>());
587
588 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
589 IsError(ERR_IO_PENDING));
590 EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
591 }
592
593 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
594 // slightly different code path.
TEST_F(WebSocketBasicStreamSocketTest,AsyncErrCloseAfterIncompleteHeader)595 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
596 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
597 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
598 CreateStream(reads, base::span<MockWrite>());
599
600 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
601 IsError(ERR_IO_PENDING));
602 EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
603 }
604
605 // An empty first frame is not ignored.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,EmptyFirstFrame)606 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) {
607 CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize));
608
609 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
610 ASSERT_EQ(1U, frames_.size());
611 EXPECT_EQ(nullptr, frames_[0]->payload);
612 EXPECT_EQ(0U, frames_[0]->header.payload_length);
613 }
614
615 // An empty frame in the middle of a message is ignored.
TEST_F(WebSocketBasicStreamSocketTest,EmptyMiddleFrame)616 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrame) {
617 MockRead reads[] = {
618 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
619 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
620 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
621 CreateStream(reads, base::span<MockWrite>());
622
623 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
624 EXPECT_EQ(1U, frames_.size());
625 frames_.clear();
626 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
627 IsError(ERR_IO_PENDING));
628 }
629
630 // An empty frame in the middle of a message that arrives separately is still
631 // ignored.
TEST_F(WebSocketBasicStreamSocketTest,EmptyMiddleFrameAsync)632 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrameAsync) {
633 MockRead reads[] = {
634 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
635 MockRead(ASYNC, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
636 // We include a pong message to verify the middle frame was actually
637 // processed.
638 MockRead(ASYNC, kValidPong, kValidPongSize)};
639 CreateStream(reads, base::span<MockWrite>());
640
641 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
642 EXPECT_EQ(1U, frames_.size());
643 frames_.clear();
644 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
645 IsError(ERR_IO_PENDING));
646 EXPECT_THAT(cb_.WaitForResult(), IsOk());
647 ASSERT_EQ(1U, frames_.size());
648 EXPECT_EQ(WebSocketFrameHeader::kOpCodePong, frames_[0]->header.opcode);
649 }
650
651 // An empty final frame is not ignored.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,EmptyFinalFrame)652 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) {
653 CreateRead(
654 MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize));
655
656 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
657 ASSERT_EQ(1U, frames_.size());
658 EXPECT_EQ(nullptr, frames_[0]->payload);
659 EXPECT_EQ(0U, frames_[0]->header.payload_length);
660 }
661
662 // An empty middle frame is ignored with a final frame present.
TEST_F(WebSocketBasicStreamSocketTest,ThreeFrameEmptyMessage)663 TEST_F(WebSocketBasicStreamSocketTest, ThreeFrameEmptyMessage) {
664 MockRead reads[] = {
665 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
666 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
667 MockRead(SYNCHRONOUS,
668 kEmptyFinalContinuationFrame,
669 kEmptyFinalContinuationFrameSize)};
670 CreateStream(reads, base::span<MockWrite>());
671
672 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
673 ASSERT_EQ(1U, frames_.size());
674 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
675 frames_.clear();
676 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
677 ASSERT_EQ(1U, frames_.size());
678 EXPECT_TRUE(frames_[0]->header.final);
679 }
680
681 // If there was a frame read at the same time as the response headers (and the
682 // handshake succeeded), then we should parse it.
TEST_F(WebSocketBasicStreamSocketTest,HttpReadBufferIsUsed)683 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
684 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
685 CreateStream(base::span<MockRead>(), base::span<MockWrite>());
686
687 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
688 ASSERT_EQ(1U, frames_.size());
689 ASSERT_TRUE(frames_[0]->payload);
690 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
691 }
692
693 // Check that a frame whose header partially arrived at the end of the response
694 // headers works correctly.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,PartialFrameHeaderInHttpResponse)695 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
696 PartialFrameHeaderInHttpResponse) {
697 SetHttpReadBuffer(kSampleFrame, 1);
698 CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1));
699
700 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
701 IsError(ERR_IO_PENDING));
702 EXPECT_THAT(cb_.WaitForResult(), IsOk());
703 ASSERT_EQ(1U, frames_.size());
704 ASSERT_TRUE(frames_[0]->payload);
705 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
706 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
707 }
708
709 // Check that a control frame which partially arrives at the end of the response
710 // headers works correctly.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,PartialControlFrameInHttpResponse)711 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
712 PartialControlFrameInHttpResponse) {
713 const size_t kPartialFrameBytes = 3;
714 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
715 CreateRead(MockRead(ASYNC,
716 kCloseFrame + kPartialFrameBytes,
717 kCloseFrameSize - kPartialFrameBytes));
718
719 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
720 IsError(ERR_IO_PENDING));
721 EXPECT_THAT(cb_.WaitForResult(), IsOk());
722 ASSERT_EQ(1U, frames_.size());
723 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
724 EXPECT_EQ(kCloseFrameSize - 2, frames_[0]->header.payload_length);
725 EXPECT_EQ(std::string(frames_[0]->payload, kCloseFrameSize - 2),
726 std::string(kCloseFrame + 2, kCloseFrameSize - 2));
727 }
728
729 // Check that a control frame which partially arrives at the end of the response
730 // headers works correctly. Synchronous version (unlikely in practice).
TEST_F(WebSocketBasicStreamSocketSingleReadTest,PartialControlFrameInHttpResponseSync)731 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
732 PartialControlFrameInHttpResponseSync) {
733 const size_t kPartialFrameBytes = 3;
734 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
735 CreateRead(MockRead(SYNCHRONOUS,
736 kCloseFrame + kPartialFrameBytes,
737 kCloseFrameSize - kPartialFrameBytes));
738
739 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
740 ASSERT_EQ(1U, frames_.size());
741 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
742 }
743
744 // Check that an invalid frame results in an error.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,SyncInvalidFrame)745 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
746 CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
747
748 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
749 stream_->ReadFrames(&frames_, cb_.callback()));
750 }
751
TEST_F(WebSocketBasicStreamSocketSingleReadTest,AsyncInvalidFrame)752 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
753 CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
754
755 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
756 IsError(ERR_IO_PENDING));
757 EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_WS_PROTOCOL_ERROR));
758 }
759
760 // A control frame without a FIN flag is invalid and should not be passed
761 // through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be
762 // fragmented."
TEST_F(WebSocketBasicStreamSocketSingleReadTest,ControlFrameWithoutFin)763 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) {
764 CreateRead(
765 MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize));
766
767 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
768 stream_->ReadFrames(&frames_, cb_.callback()));
769 EXPECT_TRUE(frames_.empty());
770 }
771
772 // A control frame over 125 characters is invalid. RFC6455 5.5 "All control
773 // frames MUST have a payload length of 125 bytes or less". Since we use a
774 // 125-byte buffer to assemble fragmented control frames, we need to detect this
775 // error before attempting to assemble the fragments.
TEST_F(WebSocketBasicStreamSocketSingleReadTest,OverlongControlFrame)776 TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) {
777 CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize));
778
779 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
780 stream_->ReadFrames(&frames_, cb_.callback()));
781 EXPECT_TRUE(frames_.empty());
782 }
783
784 // A control frame over 125 characters should still be rejected if it is split
785 // into multiple chunks.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,SplitOverlongControlFrame)786 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) {
787 const size_t kFirstChunkSize = 16;
788 expect_all_io_to_complete_ = false;
789 CreateChunkedRead(SYNCHRONOUS,
790 k126BytePong,
791 k126BytePongSize,
792 kFirstChunkSize,
793 2,
794 LAST_FRAME_BIG);
795
796 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
797 stream_->ReadFrames(&frames_, cb_.callback()));
798 EXPECT_TRUE(frames_.empty());
799 }
800
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,AsyncSplitOverlongControlFrame)801 TEST_F(WebSocketBasicStreamSocketChunkedReadTest,
802 AsyncSplitOverlongControlFrame) {
803 const size_t kFirstChunkSize = 16;
804 expect_all_io_to_complete_ = false;
805 CreateChunkedRead(ASYNC,
806 k126BytePong,
807 k126BytePongSize,
808 kFirstChunkSize,
809 2,
810 LAST_FRAME_BIG);
811
812 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
813 IsError(ERR_IO_PENDING));
814 EXPECT_THAT(cb_.WaitForResult(), IsError(ERR_WS_PROTOCOL_ERROR));
815 // The caller should not call ReadFrames() again after receiving an error
816 // other than ERR_IO_PENDING.
817 EXPECT_TRUE(frames_.empty());
818 }
819
820 // In the synchronous case, ReadFrames assembles the whole control frame before
821 // returning.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,SyncControlFrameAssembly)822 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) {
823 const size_t kChunkSize = 3;
824 CreateChunkedRead(
825 SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
826
827 EXPECT_THAT(stream_->ReadFrames(&frames_, cb_.callback()), IsOk());
828 ASSERT_EQ(1U, frames_.size());
829 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
830 }
831
832 // In the asynchronous case, the callback is not called until the control frame
833 // has been completely assembled.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,AsyncControlFrameAssembly)834 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) {
835 const size_t kChunkSize = 3;
836 CreateChunkedRead(
837 ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
838
839 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
840 IsError(ERR_IO_PENDING));
841 EXPECT_THAT(cb_.WaitForResult(), IsOk());
842 ASSERT_EQ(1U, frames_.size());
843 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
844 }
845
846 // A frame with a 1MB payload that has to be read in chunks.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,OneMegFrame)847 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OneMegFrame) {
848 // This should be equal to the definition of kSmallReadBufferFrame in
849 // websocket_basic_stream.cc.
850 const int kReadBufferSize = 1000;
851 const uint64_t kPayloadSize = 1 << 20;
852 const size_t kWireSize = kPayloadSize + kLargeFrameHeaderSize;
853 const size_t kExpectedFrameCount =
854 (kWireSize + kReadBufferSize - 1) / kReadBufferSize;
855 auto big_frame = std::make_unique<char[]>(kWireSize);
856 memcpy(big_frame.get(), "\x81\x7F", 2);
857 base::WriteBigEndian(big_frame.get() + 2, kPayloadSize);
858 memset(big_frame.get() + kLargeFrameHeaderSize, 'A', kPayloadSize);
859
860 CreateChunkedRead(ASYNC,
861 big_frame.get(),
862 kWireSize,
863 kReadBufferSize,
864 kExpectedFrameCount,
865 LAST_FRAME_BIG);
866
867 for (size_t frame = 0; frame < kExpectedFrameCount; ++frame) {
868 frames_.clear();
869 ASSERT_THAT(stream_->ReadFrames(&frames_, cb_.callback()),
870 IsError(ERR_IO_PENDING));
871 EXPECT_THAT(cb_.WaitForResult(), IsOk());
872 ASSERT_EQ(1U, frames_.size());
873 size_t expected_payload_size = kReadBufferSize;
874 if (frame == 0) {
875 expected_payload_size = kReadBufferSize - kLargeFrameHeaderSize;
876 } else if (frame == kExpectedFrameCount - 1) {
877 expected_payload_size =
878 kWireSize - kReadBufferSize * (kExpectedFrameCount - 1);
879 }
880 EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length);
881 }
882 }
883
884 // A frame with reserved flag(s) set that arrives in chunks should only have the
885 // reserved flag(s) set on the first chunk when split.
TEST_F(WebSocketBasicStreamSocketChunkedReadTest,ReservedFlagCleared)886 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ReservedFlagCleared) {
887 static const char kReservedFlagFrame[] = "\x41\x05Hello";
888 const size_t kReservedFlagFrameSize = std::size(kReservedFlagFrame) - 1;
889 const size_t kChunkSize = 5;
890
891 CreateChunkedRead(ASYNC,
892 kReservedFlagFrame,
893 kReservedFlagFrameSize,
894 kChunkSize,
895 2,
896 LAST_FRAME_BIG);
897
898 TestCompletionCallback cb[2];
899 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[0].callback()),
900 IsError(ERR_IO_PENDING));
901 EXPECT_THAT(cb[0].WaitForResult(), IsOk());
902 ASSERT_EQ(1U, frames_.size());
903 EXPECT_TRUE(frames_[0]->header.reserved1);
904
905 frames_.clear();
906 ASSERT_THAT(stream_->ReadFrames(&frames_, cb[1].callback()),
907 IsError(ERR_IO_PENDING));
908 EXPECT_THAT(cb[1].WaitForResult(), IsOk());
909 ASSERT_EQ(1U, frames_.size());
910 EXPECT_FALSE(frames_[0]->header.reserved1);
911 }
912
913 // Check that writing a frame all at once works.
TEST_F(WebSocketBasicStreamSocketWriteTest,WriteAtOnce)914 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) {
915 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
916 CreateStream(base::span<MockRead>(), writes);
917
918 EXPECT_THAT(stream_->WriteFrames(&frames_, cb_.callback()), IsOk());
919 }
920
921 // Check that completely async writing works.
TEST_F(WebSocketBasicStreamSocketWriteTest,AsyncWriteAtOnce)922 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
923 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
924 CreateStream(base::span<MockRead>(), writes);
925
926 ASSERT_THAT(stream_->WriteFrames(&frames_, cb_.callback()),
927 IsError(ERR_IO_PENDING));
928 EXPECT_THAT(cb_.WaitForResult(), IsOk());
929 }
930
931 // Check that writing a frame to an extremely full kernel buffer (so that it
932 // ends up being sent in bits) works. The WriteFrames() callback should not be
933 // called until all parts have been written.
TEST_F(WebSocketBasicStreamSocketWriteTest,WriteInBits)934 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) {
935 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
936 MockWrite(ASYNC, kWriteFrame + 4, 4),
937 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
938 CreateStream(base::span<MockRead>(), writes);
939
940 ASSERT_THAT(stream_->WriteFrames(&frames_, cb_.callback()),
941 IsError(ERR_IO_PENDING));
942 EXPECT_THAT(cb_.WaitForResult(), IsOk());
943 }
944
945 // Check that writing a Pong frame with a nullptr body works.
TEST_F(WebSocketBasicStreamSocketWriteTest,WriteNullptrPong)946 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteNullptrPong) {
947 MockWrite writes[] = {
948 MockWrite(SYNCHRONOUS, kMaskedEmptyPong, kMaskedEmptyPongSize)};
949 CreateStream(base::span<MockRead>(), writes);
950
951 auto frame =
952 std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodePong);
953 WebSocketFrameHeader& header = frame->header;
954 header.final = true;
955 header.masked = true;
956 header.payload_length = 0;
957 std::vector<std::unique_ptr<WebSocketFrame>> frames;
958 frames.push_back(std::move(frame));
959 EXPECT_THAT(stream_->WriteFrames(&frames, cb_.callback()), IsOk());
960 }
961
962 // Check that writing with a non-nullptr mask works correctly.
TEST_F(WebSocketBasicStreamSocketTest,WriteNonNulMask)963 TEST_F(WebSocketBasicStreamSocketTest, WriteNonNulMask) {
964 std::string masked_frame = std::string("\x81\x88");
965 masked_frame += std::string(kNonNulMaskingKey.key, 4);
966 masked_frame += "jiggered";
967 MockWrite writes[] = {
968 MockWrite(SYNCHRONOUS, masked_frame.data(), masked_frame.size())};
969 generator_ = &GenerateNonNulMaskingKey;
970 CreateStream(base::span<MockRead>(), writes);
971
972 auto frame =
973 std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodeText);
974 const std::string unmasked_payload = "graphics";
975 const size_t payload_size = unmasked_payload.size();
976 auto buffer = base::MakeRefCounted<IOBufferWithSize>(payload_size);
977 memcpy(buffer->data(), unmasked_payload.data(), payload_size);
978 frame->payload = buffer->data();
979 WebSocketFrameHeader& header = frame->header;
980 header.final = true;
981 header.masked = true;
982 header.payload_length = payload_size;
983 frames_.push_back(std::move(frame));
984
985 EXPECT_THAT(stream_->WriteFrames(&frames_, cb_.callback()), IsOk());
986 }
987
TEST_F(WebSocketBasicStreamSocketTest,GetExtensionsWorks)988 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
989 extensions_ = "inflate-uuencode";
990 CreateStream(base::span<MockRead>(), base::span<MockWrite>());
991
992 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
993 }
994
TEST_F(WebSocketBasicStreamSocketTest,GetSubProtocolWorks)995 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
996 sub_protocol_ = "cyberchat";
997 CreateStream(base::span<MockRead>(), base::span<MockWrite>());
998
999 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
1000 }
1001
1002 // Check that the read buffer size initialization works correctly.
TEST_F(WebSocketBasicStreamSwitchTest,GetInitialReadBufferSize)1003 TEST_F(WebSocketBasicStreamSwitchTest, GetInitialReadBufferSize) {
1004 EXPECT_EQ(buffer_size_manager_.buffer_size(),
1005 WebSocketBasicStream::BufferSize::kSmall);
1006 buffer_size_manager_.OnRead(MicrosecondsFromStart(0));
1007 EXPECT_EQ(buffer_size_manager_.buffer_size(),
1008 WebSocketBasicStream::BufferSize::kSmall);
1009 }
1010
1011 // Check that the case where the start time and the end time are the same.
TEST_F(WebSocketBasicStreamSwitchTest,ZeroSecondRead)1012 TEST_F(WebSocketBasicStreamSwitchTest, ZeroSecondRead) {
1013 buffer_size_manager_.set_window_for_test(1);
1014 buffer_size_manager_.OnRead(MicrosecondsFromStart(0));
1015 buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(0), 1000);
1016 EXPECT_EQ(buffer_size_manager_.buffer_size(),
1017 WebSocketBasicStream::BufferSize::kLarge);
1018 }
1019
1020 // Check that the read buffer size is switched for high throughput connection.
TEST_F(WebSocketBasicStreamSwitchTest,CheckSwitch)1021 TEST_F(WebSocketBasicStreamSwitchTest, CheckSwitch) {
1022 buffer_size_manager_.set_window_for_test(4);
1023 // It tests the case where 4000 bytes data is read in 2000 ms. In this case,
1024 // the read buffer size should be switched to the large one.
1025 buffer_size_manager_.OnRead(MicrosecondsFromStart(0));
1026 buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(200), 1000);
1027 buffer_size_manager_.OnRead(MicrosecondsFromStart(800));
1028 buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(1000), 1000);
1029 buffer_size_manager_.OnRead(MicrosecondsFromStart(1300));
1030 buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(1500), 1000);
1031 buffer_size_manager_.OnRead(MicrosecondsFromStart(1800));
1032 buffer_size_manager_.OnReadComplete(MicrosecondsFromStart(2000), 1000);
1033 EXPECT_EQ(buffer_size_manager_.buffer_size(),
1034 WebSocketBasicStream::BufferSize::kLarge);
1035 }
1036
1037 } // namespace
1038 } // namespace net
1039