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

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: Make changes suggested by rsleevi, exclude SSLClientSocketOpenSSL from this CL 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
« no previous file with comments | « net/socket/ssl_client_socket_nss.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // NOTE: this is a test for SSLClientSocket rather than SSLServerSocket.
480 TEST_F(SSLServerSocketTest, ClientWriteAfterServerClose) {
481 Initialize();
482
483 TestCompletionCallback connect_callback;
484 TestCompletionCallback handshake_callback;
485
486 // Establish connection.
487 int client_ret = client_socket_->Connect(connect_callback.callback());
488 ASSERT_TRUE(client_ret == net::OK || client_ret == net::ERR_IO_PENDING);
489
490 int server_ret = server_socket_->Handshake(handshake_callback.callback());
491 ASSERT_TRUE(server_ret == net::OK || server_ret == net::ERR_IO_PENDING);
492
493 client_ret = connect_callback.GetResult(client_ret);
494 ASSERT_EQ(net::OK, client_ret);
495 server_ret = handshake_callback.GetResult(server_ret);
496 ASSERT_EQ(net::OK, server_ret);
497
498 scoped_refptr<net::StringIOBuffer> write_buf =
499 new net::StringIOBuffer("testing123");
500
501 // The server closes the connection. The server needs to write some
502 // data first so that the client's Read() calls from the transport
503 // socket won't return ERR_IO_PENDING. This ensures that the client
504 // will call Read() on the transport socket again.
505 TestCompletionCallback write_callback;
506
507 server_ret = server_socket_->Write(write_buf, write_buf->size(),
508 write_callback.callback());
509 EXPECT_TRUE(server_ret > 0 || server_ret == net::ERR_IO_PENDING);
510
511 server_ret = write_callback.GetResult(server_ret);
512 EXPECT_GT(server_ret, 0);
513
514 server_socket_->Disconnect();
515
516 // The client writes some data. This should not cause an infinite loop.
517 client_ret = client_socket_->Write(write_buf, write_buf->size(),
518 write_callback.callback());
519 EXPECT_TRUE(client_ret > 0 || client_ret == net::ERR_IO_PENDING);
520
521 client_ret = write_callback.GetResult(client_ret);
522 EXPECT_GT(client_ret, 0);
523
524 MessageLoop::current()->PostDelayedTask(
525 FROM_HERE, MessageLoop::QuitClosure(),
526 base::TimeDelta::FromMilliseconds(10));
527 MessageLoop::current()->Run();
528 }
529
432 // This test executes ExportKeyingMaterial() on the client and server sockets, 530 // This test executes ExportKeyingMaterial() on the client and server sockets,
433 // after connecting them, and verifies that the results match. 531 // after connecting them, and verifies that the results match.
434 // This test will fail if False Start is enabled (see crbug.com/90208). 532 // This test will fail if False Start is enabled (see crbug.com/90208).
435 TEST_F(SSLServerSocketTest, ExportKeyingMaterial) { 533 TEST_F(SSLServerSocketTest, ExportKeyingMaterial) {
436 Initialize(); 534 Initialize();
437 535
438 TestCompletionCallback connect_callback; 536 TestCompletionCallback connect_callback;
439 TestCompletionCallback handshake_callback; 537 TestCompletionCallback handshake_callback;
440 538
441 int client_ret = client_socket_->Connect(connect_callback.callback()); 539 int client_ret = client_socket_->Connect(connect_callback.callback());
(...skipping 29 matching lines...) Expand all
471 unsigned char client_bad[kKeyingMaterialSize]; 569 unsigned char client_bad[kKeyingMaterialSize];
472 rv = client_socket_->ExportKeyingMaterial(kKeyingLabelBad, 570 rv = client_socket_->ExportKeyingMaterial(kKeyingLabelBad,
473 false, kKeyingContext, 571 false, kKeyingContext,
474 client_bad, sizeof(client_bad)); 572 client_bad, sizeof(client_bad));
475 ASSERT_EQ(rv, net::OK); 573 ASSERT_EQ(rv, net::OK);
476 EXPECT_NE(0, memcmp(server_out, client_bad, sizeof(server_out))); 574 EXPECT_NE(0, memcmp(server_out, client_bad, sizeof(server_out)));
477 } 575 }
478 #endif 576 #endif
479 577
480 } // namespace net 578 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_nss.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698