OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This test suite uses SSLClientSocket to test the implementation of | 5 // This test suite uses SSLClientSocket to test the implementation of |
6 // SSLServerSocket. In order to establish connections between the sockets | 6 // SSLServerSocket. In order to establish connections between the sockets |
7 // we need two additional classes: | 7 // we need two additional classes: |
8 // 1. FakeSocket | 8 // 1. FakeSocket |
9 // Connects SSL socket to FakeDataChannel. This class is just a stub. | 9 // Connects SSL socket to FakeDataChannel. This class is just a stub. |
10 // | 10 // |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 #include "testing/platform_test.h" | 47 #include "testing/platform_test.h" |
48 | 48 |
49 namespace net { | 49 namespace net { |
50 | 50 |
51 namespace { | 51 namespace { |
52 | 52 |
53 class FakeDataChannel { | 53 class FakeDataChannel { |
54 public: | 54 public: |
55 FakeDataChannel() | 55 FakeDataChannel() |
56 : read_buf_len_(0), | 56 : read_buf_len_(0), |
57 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 57 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
58 closed_(false), | |
59 write_called_after_close_(false) { | |
58 } | 60 } |
59 | 61 |
60 int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { | 62 int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { |
63 if (closed_) | |
64 return 0; | |
61 if (data_.empty()) { | 65 if (data_.empty()) { |
62 read_callback_ = callback; | 66 read_callback_ = callback; |
63 read_buf_ = buf; | 67 read_buf_ = buf; |
64 read_buf_len_ = buf_len; | 68 read_buf_len_ = buf_len; |
65 return net::ERR_IO_PENDING; | 69 return net::ERR_IO_PENDING; |
66 } | 70 } |
67 return PropogateData(buf, buf_len); | 71 return PropogateData(buf, buf_len); |
68 } | 72 } |
69 | 73 |
70 int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { | 74 int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { |
75 if (closed_) { | |
76 if (write_called_after_close_) | |
77 return net::ERR_CONNECTION_RESET; | |
78 write_called_after_close_ = true; | |
79 write_callback_ = callback; | |
80 MessageLoop::current()->PostTask( | |
81 FROM_HERE, base::Bind(&FakeDataChannel::DoWriteCallback, | |
82 weak_factory_.GetWeakPtr())); | |
83 return net::ERR_IO_PENDING; | |
84 } | |
71 data_.push(new net::DrainableIOBuffer(buf, buf_len)); | 85 data_.push(new net::DrainableIOBuffer(buf, buf_len)); |
72 MessageLoop::current()->PostTask( | 86 MessageLoop::current()->PostTask( |
73 FROM_HERE, base::Bind(&FakeDataChannel::DoReadCallback, | 87 FROM_HERE, base::Bind(&FakeDataChannel::DoReadCallback, |
74 weak_factory_.GetWeakPtr())); | 88 weak_factory_.GetWeakPtr())); |
75 return buf_len; | 89 return buf_len; |
76 } | 90 } |
77 | 91 |
92 // Closes the FakeDataChannel. After Close() is called, Read() returns 0, | |
93 // indicating EOF, and Write() fails with ERR_CONNECTION_RESET. Note that | |
94 // after the FakeDataChannel is closed, the first Write() call completes | |
95 // asynchronously, which is necessary to reproduce bug 127822. | |
96 void Close() { | |
97 closed_ = true; | |
98 } | |
99 | |
78 private: | 100 private: |
79 void DoReadCallback() { | 101 void DoReadCallback() { |
80 if (read_callback_.is_null() || data_.empty()) | 102 if (read_callback_.is_null() || data_.empty()) |
81 return; | 103 return; |
82 | 104 |
83 int copied = PropogateData(read_buf_, read_buf_len_); | 105 int copied = PropogateData(read_buf_, read_buf_len_); |
84 CompletionCallback callback = read_callback_; | 106 CompletionCallback callback = read_callback_; |
85 read_callback_.Reset(); | 107 read_callback_.Reset(); |
86 read_buf_ = NULL; | 108 read_buf_ = NULL; |
87 read_buf_len_ = 0; | 109 read_buf_len_ = 0; |
88 callback.Run(copied); | 110 callback.Run(copied); |
89 } | 111 } |
90 | 112 |
113 void DoWriteCallback() { | |
114 if (write_callback_.is_null()) | |
115 return; | |
116 | |
117 CompletionCallback callback = write_callback_; | |
118 write_callback_.Reset(); | |
119 callback.Run(net::ERR_CONNECTION_RESET); | |
120 } | |
121 | |
91 int PropogateData(scoped_refptr<net::IOBuffer> read_buf, int read_buf_len) { | 122 int PropogateData(scoped_refptr<net::IOBuffer> read_buf, int read_buf_len) { |
92 scoped_refptr<net::DrainableIOBuffer> buf = data_.front(); | 123 scoped_refptr<net::DrainableIOBuffer> buf = data_.front(); |
93 int copied = std::min(buf->BytesRemaining(), read_buf_len); | 124 int copied = std::min(buf->BytesRemaining(), read_buf_len); |
94 memcpy(read_buf->data(), buf->data(), copied); | 125 memcpy(read_buf->data(), buf->data(), copied); |
95 buf->DidConsume(copied); | 126 buf->DidConsume(copied); |
96 | 127 |
97 if (!buf->BytesRemaining()) | 128 if (!buf->BytesRemaining()) |
98 data_.pop(); | 129 data_.pop(); |
99 return copied; | 130 return copied; |
100 } | 131 } |
101 | 132 |
102 CompletionCallback read_callback_; | 133 CompletionCallback read_callback_; |
103 scoped_refptr<net::IOBuffer> read_buf_; | 134 scoped_refptr<net::IOBuffer> read_buf_; |
104 int read_buf_len_; | 135 int read_buf_len_; |
105 | 136 |
137 CompletionCallback write_callback_; | |
138 | |
106 std::queue<scoped_refptr<net::DrainableIOBuffer> > data_; | 139 std::queue<scoped_refptr<net::DrainableIOBuffer> > data_; |
107 | 140 |
108 base::WeakPtrFactory<FakeDataChannel> weak_factory_; | 141 base::WeakPtrFactory<FakeDataChannel> weak_factory_; |
109 | 142 |
143 // True if Close() has been called. | |
144 bool closed_; | |
145 | |
146 // Controls the completion of Write() after the FakeDataChannel is closed. | |
147 // After the FakeDataChannel is closed, the first Write() call completes | |
148 // asynchronously. | |
149 bool write_called_after_close_; | |
150 | |
110 DISALLOW_COPY_AND_ASSIGN(FakeDataChannel); | 151 DISALLOW_COPY_AND_ASSIGN(FakeDataChannel); |
111 }; | 152 }; |
112 | 153 |
113 class FakeSocket : public StreamSocket { | 154 class FakeSocket : public StreamSocket { |
114 public: | 155 public: |
115 FakeSocket(FakeDataChannel* incoming_channel, | 156 FakeSocket(FakeDataChannel* incoming_channel, |
116 FakeDataChannel* outgoing_channel) | 157 FakeDataChannel* outgoing_channel) |
117 : incoming_(incoming_channel), | 158 : incoming_(incoming_channel), |
118 outgoing_(outgoing_channel) { | 159 outgoing_(outgoing_channel) { |
119 } | 160 } |
(...skipping 20 matching lines...) Expand all Loading... | |
140 } | 181 } |
141 | 182 |
142 virtual bool SetSendBufferSize(int32 size) OVERRIDE { | 183 virtual bool SetSendBufferSize(int32 size) OVERRIDE { |
143 return true; | 184 return true; |
144 } | 185 } |
145 | 186 |
146 virtual int Connect(const CompletionCallback& callback) OVERRIDE { | 187 virtual int Connect(const CompletionCallback& callback) OVERRIDE { |
147 return net::OK; | 188 return net::OK; |
148 } | 189 } |
149 | 190 |
150 virtual void Disconnect() OVERRIDE {} | 191 virtual void Disconnect() OVERRIDE { |
192 incoming_->Close(); | |
193 outgoing_->Close(); | |
194 } | |
151 | 195 |
152 virtual bool IsConnected() const OVERRIDE { | 196 virtual bool IsConnected() const OVERRIDE { |
153 return true; | 197 return true; |
154 } | 198 } |
155 | 199 |
156 virtual bool IsConnectedAndIdle() const OVERRIDE { | 200 virtual bool IsConnectedAndIdle() const OVERRIDE { |
157 return true; | 201 return true; |
158 } | 202 } |
159 | 203 |
160 virtual int GetPeerAddress(AddressList* address) const OVERRIDE { | 204 virtual int GetPeerAddress(AddressList* address) const OVERRIDE { |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING); | 466 EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING); |
423 server_ret = read_callback.GetResult(server_ret); | 467 server_ret = read_callback.GetResult(server_ret); |
424 ASSERT_GT(server_ret, 0); | 468 ASSERT_GT(server_ret, 0); |
425 read_buf->DidConsume(server_ret); | 469 read_buf->DidConsume(server_ret); |
426 } | 470 } |
427 EXPECT_EQ(write_buf->size(), read_buf->BytesConsumed()); | 471 EXPECT_EQ(write_buf->size(), read_buf->BytesConsumed()); |
428 read_buf->SetOffset(0); | 472 read_buf->SetOffset(0); |
429 EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size())); | 473 EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size())); |
430 } | 474 } |
431 | 475 |
476 // A regression test for bug 127822 (http://crbug.com/127822). | |
477 // If the server closes the connection after the handshake is finished, | |
478 // the client's Write() call should not cause an infinite loop. | |
479 TEST_F(SSLServerSocketTest, WriteAfterPeerClose) { | |
Ryan Sleevi
2012/05/16 02:16:46
Just to make sure - this is really testing the beh
wtc
2012/05/16 03:04:29
Yes. I added a comment to clarify this.
| |
480 Initialize(); | |
481 | |
482 TestCompletionCallback connect_callback; | |
483 TestCompletionCallback handshake_callback; | |
484 | |
485 // Establish connection. | |
486 int client_ret = client_socket_->Connect(connect_callback.callback()); | |
487 ASSERT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING); | |
488 | |
489 int server_ret = server_socket_->Handshake(handshake_callback.callback()); | |
490 ASSERT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING); | |
491 | |
492 client_ret = connect_callback.GetResult(client_ret); | |
493 ASSERT_EQ(net::OK, client_ret); | |
494 server_ret = handshake_callback.GetResult(server_ret); | |
495 ASSERT_EQ(net::OK, server_ret); | |
496 | |
497 scoped_refptr<net::StringIOBuffer> write_buf = | |
498 new net::StringIOBuffer("testing123"); | |
499 | |
500 // The server closes the connection. The server needs to write some | |
501 // data first so that the client's Read() calls from the transport | |
502 // socket won't return ERR_IO_PENDING. This ensures that the client | |
503 // will call Read() on the transport socket again. | |
504 TestCompletionCallback write_callback; | |
505 | |
506 server_ret = server_socket_->Write(write_buf, write_buf->size(), | |
507 write_callback.callback()); | |
508 EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING); | |
509 | |
510 server_ret = write_callback.GetResult(server_ret); | |
511 EXPECT_GT(server_ret, 0); | |
512 | |
513 server_socket_->Disconnect(); | |
514 | |
515 // The client writes some data. This should not cause an infinite loop. | |
516 client_ret = client_socket_->Write(write_buf, write_buf->size(), | |
517 write_callback.callback()); | |
518 EXPECT_TRUE(client_ret > 0 || client_ret == net::ERR_IO_PENDING); | |
519 | |
520 client_ret = write_callback.GetResult(client_ret); | |
521 EXPECT_GT(client_ret, 0); | |
522 | |
523 MessageLoop::current()->PostDelayedTask( | |
524 FROM_HERE, MessageLoop::QuitClosure(), | |
525 base::TimeDelta::FromMilliseconds(10)); | |
526 MessageLoop::current()->Run(); | |
527 } | |
528 | |
432 // This test executes ExportKeyingMaterial() on the client and server sockets, | 529 // This test executes ExportKeyingMaterial() on the client and server sockets, |
433 // after connecting them, and verifies that the results match. | 530 // after connecting them, and verifies that the results match. |
434 // This test will fail if False Start is enabled (see crbug.com/90208). | 531 // This test will fail if False Start is enabled (see crbug.com/90208). |
435 TEST_F(SSLServerSocketTest, ExportKeyingMaterial) { | 532 TEST_F(SSLServerSocketTest, ExportKeyingMaterial) { |
436 Initialize(); | 533 Initialize(); |
437 | 534 |
438 TestCompletionCallback connect_callback; | 535 TestCompletionCallback connect_callback; |
439 TestCompletionCallback handshake_callback; | 536 TestCompletionCallback handshake_callback; |
440 | 537 |
441 int client_ret = client_socket_->Connect(connect_callback.callback()); | 538 int client_ret = client_socket_->Connect(connect_callback.callback()); |
(...skipping 29 matching lines...) Expand all Loading... | |
471 unsigned char client_bad[kKeyingMaterialSize]; | 568 unsigned char client_bad[kKeyingMaterialSize]; |
472 rv = client_socket_->ExportKeyingMaterial(kKeyingLabelBad, | 569 rv = client_socket_->ExportKeyingMaterial(kKeyingLabelBad, |
473 false, kKeyingContext, | 570 false, kKeyingContext, |
474 client_bad, sizeof(client_bad)); | 571 client_bad, sizeof(client_bad)); |
475 ASSERT_EQ(rv, net::OK); | 572 ASSERT_EQ(rv, net::OK); |
476 EXPECT_NE(0, memcmp(server_out, client_bad, sizeof(server_out))); | 573 EXPECT_NE(0, memcmp(server_out, client_bad, sizeof(server_out))); |
477 } | 574 } |
478 #endif | 575 #endif |
479 | 576 |
480 } // namespace net | 577 } // namespace net |
OLD | NEW |