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

Side by Side Diff: net/socket_stream/socket_stream.cc

Issue 3076024: Fix WebSocket crash bug. (Closed)
Patch Set: fix for tyoshino's comment Created 10 years, 4 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
« no previous file with comments | « net/socket_stream/socket_stream.h ('k') | net/socket_stream/socket_stream_unittest.cc » ('j') | 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 // TODO(ukai): code is similar with http_network_transaction.cc. We should 5 // TODO(ukai): code is similar with http_network_transaction.cc. We should
6 // think about ways to share code, if possible. 6 // think about ways to share code, if possible.
7 7
8 #include "net/socket_stream/socket_stream.h" 8 #include "net/socket_stream/socket_stream.h"
9 9
10 #include <set> 10 #include <set>
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 ALLOW_THIS_IN_INITIALIZER_LIST( 59 ALLOW_THIS_IN_INITIALIZER_LIST(
60 read_callback_(this, &SocketStream::OnReadCompleted)), 60 read_callback_(this, &SocketStream::OnReadCompleted)),
61 ALLOW_THIS_IN_INITIALIZER_LIST( 61 ALLOW_THIS_IN_INITIALIZER_LIST(
62 write_callback_(this, &SocketStream::OnWriteCompleted)), 62 write_callback_(this, &SocketStream::OnWriteCompleted)),
63 read_buf_(NULL), 63 read_buf_(NULL),
64 write_buf_(NULL), 64 write_buf_(NULL),
65 current_write_buf_(NULL), 65 current_write_buf_(NULL),
66 write_buf_offset_(0), 66 write_buf_offset_(0),
67 write_buf_size_(0), 67 write_buf_size_(0),
68 closing_(false), 68 closing_(false),
69 server_closed_(false),
69 metrics_(new SocketStreamMetrics(url)) { 70 metrics_(new SocketStreamMetrics(url)) {
70 DCHECK(MessageLoop::current()) << 71 DCHECK(MessageLoop::current()) <<
71 "The current MessageLoop must exist"; 72 "The current MessageLoop must exist";
72 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 73 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
73 "The current MessageLoop must be TYPE_IO"; 74 "The current MessageLoop must be TYPE_IO";
74 DCHECK(delegate_); 75 DCHECK(delegate_);
75 } 76 }
76 77
77 SocketStream::~SocketStream() { 78 SocketStream::~SocketStream() {
78 set_context(NULL); 79 set_context(NULL);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 DCHECK(MessageLoop::current()) << 182 DCHECK(MessageLoop::current()) <<
182 "The current MessageLoop must exist"; 183 "The current MessageLoop must exist";
183 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 184 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
184 "The current MessageLoop must be TYPE_IO"; 185 "The current MessageLoop must be TYPE_IO";
185 // If next_state_ is STATE_NONE, the socket was not opened, or already 186 // If next_state_ is STATE_NONE, the socket was not opened, or already
186 // closed. So, return immediately. 187 // closed. So, return immediately.
187 // Otherwise, it might call Finish() more than once, so breaks balance 188 // Otherwise, it might call Finish() more than once, so breaks balance
188 // of AddRef() and Release() in Connect() and Finish(), respectively. 189 // of AddRef() and Release() in Connect() and Finish(), respectively.
189 if (next_state_ == STATE_NONE) 190 if (next_state_ == STATE_NONE)
190 return; 191 return;
191 closing_ = true;
192 // Close asynchronously, so that delegate won't be called
193 // back before returning Close().
194 MessageLoop::current()->PostTask( 192 MessageLoop::current()->PostTask(
195 FROM_HERE, 193 FROM_HERE,
196 NewRunnableMethod(this, &SocketStream::DoLoop, OK)); 194 NewRunnableMethod(this, &SocketStream::DoClose));
195 }
196
197 void SocketStream::DoClose() {
198 closing_ = true;
199 // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket establishing
200 // connection. If next_state_ is STATE_AUTH_REQUIRED, it's waiting for
201 // restarting. In these states, we'll close the SocketStream now.
202 if (next_state_ == STATE_TCP_CONNECT || next_state_ == STATE_AUTH_REQUIRED) {
203 DoLoop(ERR_ABORTED);
204 return;
205 }
206 // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close
207 // the SocketStream.
208 // If it's writing now, we should defer the closing after the current
209 // writing is completed.
210 if (next_state_ == STATE_READ_WRITE && !current_write_buf_)
211 DoLoop(ERR_ABORTED);
212
213 // In other next_state_, we'll wait for callback of other APIs, such as
214 // ResolveProxy().
197 } 215 }
198 216
199 void SocketStream::RestartWithAuth( 217 void SocketStream::RestartWithAuth(
200 const string16& username, const string16& password) { 218 const string16& username, const string16& password) {
201 DCHECK(MessageLoop::current()) << 219 DCHECK(MessageLoop::current()) <<
202 "The current MessageLoop must exist"; 220 "The current MessageLoop must exist";
203 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 221 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
204 "The current MessageLoop must be TYPE_IO"; 222 "The current MessageLoop must be TYPE_IO";
205 DCHECK(auth_handler_.get()); 223 DCHECK(auth_handler_.get());
206 if (!socket_.get()) { 224 if (!socket_.get()) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 return OK; 341 return OK;
324 } 342 }
325 343
326 void SocketStream::OnIOCompleted(int result) { 344 void SocketStream::OnIOCompleted(int result) {
327 DoLoop(result); 345 DoLoop(result);
328 } 346 }
329 347
330 void SocketStream::OnReadCompleted(int result) { 348 void SocketStream::OnReadCompleted(int result) {
331 if (result == 0) { 349 if (result == 0) {
332 // 0 indicates end-of-file, so socket was closed. 350 // 0 indicates end-of-file, so socket was closed.
333 next_state_ = STATE_CLOSE; 351 // Don't close the socket if it's still writing.
352 server_closed_ = true;
334 } else if (result > 0 && read_buf_) { 353 } else if (result > 0 && read_buf_) {
335 result = DidReceiveData(result); 354 result = DidReceiveData(result);
336 } 355 }
337 DoLoop(result); 356 DoLoop(result);
338 } 357 }
339 358
340 void SocketStream::OnWriteCompleted(int result) { 359 void SocketStream::OnWriteCompleted(int result) {
341 if (result >= 0 && write_buf_) { 360 if (result >= 0 && write_buf_) {
342 result = DidSendData(result); 361 result = DidSendData(result);
343 } 362 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 case STATE_SSL_CONNECT: 420 case STATE_SSL_CONNECT:
402 DCHECK_EQ(OK, result); 421 DCHECK_EQ(OK, result);
403 result = DoSSLConnect(); 422 result = DoSSLConnect();
404 break; 423 break;
405 case STATE_SSL_CONNECT_COMPLETE: 424 case STATE_SSL_CONNECT_COMPLETE:
406 result = DoSSLConnectComplete(result); 425 result = DoSSLConnectComplete(result);
407 break; 426 break;
408 case STATE_READ_WRITE: 427 case STATE_READ_WRITE:
409 result = DoReadWrite(result); 428 result = DoReadWrite(result);
410 break; 429 break;
430 case STATE_AUTH_REQUIRED:
431 NOTREACHED() << "Should not run DoLoop in STATE_AUTH_REQUIRED state.";
432 Finish(result);
433 return;
411 case STATE_CLOSE: 434 case STATE_CLOSE:
412 DCHECK_LE(result, OK); 435 DCHECK_LE(result, OK);
413 Finish(result); 436 Finish(result);
414 return; 437 return;
415 default: 438 default:
416 NOTREACHED() << "bad state"; 439 NOTREACHED() << "bad state " << state;
417 Finish(result); 440 Finish(result);
418 return; 441 return;
419 } 442 }
420 // If the connection is not established yet and had actual errors, 443 // If the connection is not established yet and had actual errors,
421 // close the connection. 444 // close the connection.
422 if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) { 445 if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
423 DCHECK_EQ(next_state_, STATE_CLOSE); 446 DCHECK_EQ(next_state_, STATE_CLOSE);
424 net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT, 447 net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT,
425 new NetLogIntegerParameter("net_error", result)); 448 new NetLogIntegerParameter("net_error", result));
426 } 449 }
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 // let's close the socket. 857 // let's close the socket.
835 // We don't care about receiving data after the socket is closed. 858 // We don't care about receiving data after the socket is closed.
836 if (closing_ && !write_buf_ && pending_write_bufs_.empty()) { 859 if (closing_ && !write_buf_ && pending_write_bufs_.empty()) {
837 socket_->Disconnect(); 860 socket_->Disconnect();
838 next_state_ = STATE_CLOSE; 861 next_state_ = STATE_CLOSE;
839 return OK; 862 return OK;
840 } 863 }
841 864
842 next_state_ = STATE_READ_WRITE; 865 next_state_ = STATE_READ_WRITE;
843 866
844 if (!read_buf_) { 867 // If server already closed the socket, we don't try to read.
845 // No read pending. 868 if (!server_closed_) {
846 read_buf_ = new IOBuffer(kReadBufferSize); 869 if (!read_buf_) {
847 result = socket_->Read(read_buf_, kReadBufferSize, &read_callback_); 870 // No read pending and server didn't close the socket.
848 if (result > 0) { 871 read_buf_ = new IOBuffer(kReadBufferSize);
849 return DidReceiveData(result); 872 result = socket_->Read(read_buf_, kReadBufferSize, &read_callback_);
850 } else if (result == 0) { 873 if (result > 0) {
851 // 0 indicates end-of-file, so socket was closed. 874 return DidReceiveData(result);
852 next_state_ = STATE_CLOSE; 875 } else if (result == 0) {
853 return ERR_CONNECTION_CLOSED; 876 // 0 indicates end-of-file, so socket was closed.
877 next_state_ = STATE_CLOSE;
878 server_closed_ = true;
879 return ERR_CONNECTION_CLOSED;
880 }
881 // If read is pending, try write as well.
882 // Otherwise, return the result and do next loop (to close the
883 // connection).
884 if (result != ERR_IO_PENDING) {
885 next_state_ = STATE_CLOSE;
886 server_closed_ = true;
887 return result;
888 }
854 } 889 }
855 // If read is pending, try write as well. 890 // Read is pending.
856 // Otherwise, return the result and do next loop (to close the connection). 891 DCHECK(read_buf_);
857 if (result != ERR_IO_PENDING) {
858 next_state_ = STATE_CLOSE;
859 return result;
860 }
861 } 892 }
862 // Read is pending.
863 DCHECK(read_buf_);
864 893
865 if (write_buf_ && !current_write_buf_) { 894 if (write_buf_ && !current_write_buf_) {
866 // No write pending. 895 // No write pending.
867 current_write_buf_ = new DrainableIOBuffer(write_buf_, write_buf_size_); 896 current_write_buf_ = new DrainableIOBuffer(write_buf_, write_buf_size_);
868 current_write_buf_->SetOffset(write_buf_offset_); 897 current_write_buf_->SetOffset(write_buf_offset_);
869 result = socket_->Write(current_write_buf_, 898 result = socket_->Write(current_write_buf_,
870 current_write_buf_->BytesRemaining(), 899 current_write_buf_->BytesRemaining(),
871 &write_callback_); 900 &write_callback_);
872 if (result > 0) { 901 if (result > 0) {
873 return DidSendData(result); 902 return DidSendData(result);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 1015
987 SSLConfigService* SocketStream::ssl_config_service() const { 1016 SSLConfigService* SocketStream::ssl_config_service() const {
988 return context_->ssl_config_service(); 1017 return context_->ssl_config_service();
989 } 1018 }
990 1019
991 ProxyService* SocketStream::proxy_service() const { 1020 ProxyService* SocketStream::proxy_service() const {
992 return context_->proxy_service(); 1021 return context_->proxy_service();
993 } 1022 }
994 1023
995 } // namespace net 1024 } // namespace net
OLDNEW
« no previous file with comments | « net/socket_stream/socket_stream.h ('k') | net/socket_stream/socket_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698