Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(554)

Side by Side Diff: net/socket/ssl_server_socket_unittest.cc

Issue 10382186: Prevent the infinite loop inside SSLClientSocketNSS::OnSendComplete. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Add SSLClientSocketOpenSSL fix Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW
« net/socket/ssl_client_socket_nss.cc ('K') | « net/socket/ssl_client_socket_openssl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698