| OLD | NEW | 
|---|
| 1 // Copyright (c) 2006-2008 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 #include "net/socket/tcp_client_socket_libevent.h" | 5 #include "net/socket/tcp_client_socket_libevent.h" | 
| 6 | 6 | 
| 7 #include <errno.h> | 7 #include <errno.h> | 
| 8 #include <fcntl.h> | 8 #include <fcntl.h> | 
| 9 #include <netdb.h> | 9 #include <netdb.h> | 
| 10 #include <sys/socket.h> | 10 #include <sys/socket.h> | 
| 11 #include <netinet/tcp.h> | 11 #include <netinet/tcp.h> | 
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 115       return true; | 115       return true; | 
| 116     default: | 116     default: | 
| 117       return false; | 117       return false; | 
| 118   } | 118   } | 
| 119 } | 119 } | 
| 120 | 120 | 
| 121 }  // namespace | 121 }  // namespace | 
| 122 | 122 | 
| 123 //----------------------------------------------------------------------------- | 123 //----------------------------------------------------------------------------- | 
| 124 | 124 | 
| 125 TCPClientSocketLibevent::TCPClientSocketLibevent(const AddressList& addresses) | 125 TCPClientSocketLibevent::TCPClientSocketLibevent(const AddressList& addresses, | 
|  | 126                                                  net::NetLog* net_log) | 
| 126     : socket_(kInvalidSocket), | 127     : socket_(kInvalidSocket), | 
| 127       addresses_(addresses), | 128       addresses_(addresses), | 
| 128       current_ai_(addresses_.head()), | 129       current_ai_(addresses_.head()), | 
| 129       waiting_connect_(false), | 130       waiting_connect_(false), | 
| 130       read_watcher_(this), | 131       read_watcher_(this), | 
| 131       write_watcher_(this), | 132       write_watcher_(this), | 
| 132       read_callback_(NULL), | 133       read_callback_(NULL), | 
| 133       write_callback_(NULL) { | 134       write_callback_(NULL), | 
|  | 135       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 
| 134 } | 136 } | 
| 135 | 137 | 
| 136 TCPClientSocketLibevent::~TCPClientSocketLibevent() { | 138 TCPClientSocketLibevent::~TCPClientSocketLibevent() { | 
| 137   Disconnect(); | 139   Disconnect(); | 
|  | 140   net_log_.AddEvent(NetLog::TYPE_TCP_SOCKET_DONE); | 
| 138 } | 141 } | 
| 139 | 142 | 
| 140 int TCPClientSocketLibevent::Connect(CompletionCallback* callback, | 143 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) { | 
| 141                                      const BoundNetLog& net_log) { |  | 
| 142   // If already connected, then just return OK. | 144   // If already connected, then just return OK. | 
| 143   if (socket_ != kInvalidSocket) | 145   if (socket_ != kInvalidSocket) | 
| 144     return OK; | 146     return OK; | 
| 145 | 147 | 
| 146   DCHECK(!waiting_connect_); | 148   DCHECK(!waiting_connect_); | 
| 147   DCHECK(!net_log_.net_log()); |  | 
| 148 | 149 | 
| 149   TRACE_EVENT_BEGIN("socket.connect", this, ""); | 150   TRACE_EVENT_BEGIN("socket.connect", this, ""); | 
| 150 | 151 | 
| 151   net_log.BeginEvent(NetLog::TYPE_TCP_CONNECT); | 152   net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT); | 
| 152 | 153 | 
| 153   int rv = DoConnect(); | 154   int rv = DoConnect(); | 
| 154 | 155 | 
| 155   if (rv == ERR_IO_PENDING) { | 156   if (rv == ERR_IO_PENDING) { | 
| 156     // Synchronous operation not supported. | 157     // Synchronous operation not supported. | 
| 157     DCHECK(callback); | 158     DCHECK(callback); | 
| 158 | 159 | 
| 159     net_log_ = net_log; |  | 
| 160     waiting_connect_ = true; | 160     waiting_connect_ = true; | 
| 161     write_callback_ = callback; | 161     write_callback_ = callback; | 
| 162   } else { | 162   } else { | 
| 163     TRACE_EVENT_END("socket.connect", this, ""); | 163     TRACE_EVENT_END("socket.connect", this, ""); | 
| 164     net_log.EndEvent(NetLog::TYPE_TCP_CONNECT); | 164     net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); | 
| 165   } | 165   } | 
| 166 | 166 | 
| 167   return rv; | 167   return rv; | 
| 168 } | 168 } | 
| 169 | 169 | 
| 170 int TCPClientSocketLibevent::DoConnect() { | 170 int TCPClientSocketLibevent::DoConnect() { | 
| 171   while (true) { | 171   while (true) { | 
| 172     DCHECK(current_ai_); | 172     DCHECK(current_ai_); | 
| 173 | 173 | 
| 174     int rv = CreateSocket(current_ai_); | 174     int rv = CreateSocket(current_ai_); | 
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 270   DCHECK(!waiting_connect_); | 270   DCHECK(!waiting_connect_); | 
| 271   DCHECK(!read_callback_); | 271   DCHECK(!read_callback_); | 
| 272   // Synchronous operation not supported | 272   // Synchronous operation not supported | 
| 273   DCHECK(callback); | 273   DCHECK(callback); | 
| 274   DCHECK_GT(buf_len, 0); | 274   DCHECK_GT(buf_len, 0); | 
| 275 | 275 | 
| 276   TRACE_EVENT_BEGIN("socket.read", this, ""); | 276   TRACE_EVENT_BEGIN("socket.read", this, ""); | 
| 277   int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); | 277   int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); | 
| 278   if (nread >= 0) { | 278   if (nread >= 0) { | 
| 279     TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", nread)); | 279     TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", nread)); | 
|  | 280     net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread); | 
| 280     return nread; | 281     return nread; | 
| 281   } | 282   } | 
| 282   if (errno != EAGAIN && errno != EWOULDBLOCK) { | 283   if (errno != EAGAIN && errno != EWOULDBLOCK) { | 
| 283     DLOG(INFO) << "read failed, errno " << errno; | 284     DLOG(INFO) << "read failed, errno " << errno; | 
| 284     return MapPosixError(errno); | 285     return MapPosixError(errno); | 
| 285   } | 286   } | 
| 286 | 287 | 
| 287   if (!MessageLoopForIO::current()->WatchFileDescriptor( | 288   if (!MessageLoopForIO::current()->WatchFileDescriptor( | 
| 288           socket_, true, MessageLoopForIO::WATCH_READ, | 289           socket_, true, MessageLoopForIO::WATCH_READ, | 
| 289           &read_socket_watcher_, &read_watcher_)) { | 290           &read_socket_watcher_, &read_watcher_)) { | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 304   DCHECK(!waiting_connect_); | 305   DCHECK(!waiting_connect_); | 
| 305   DCHECK(!write_callback_); | 306   DCHECK(!write_callback_); | 
| 306   // Synchronous operation not supported | 307   // Synchronous operation not supported | 
| 307   DCHECK(callback); | 308   DCHECK(callback); | 
| 308   DCHECK_GT(buf_len, 0); | 309   DCHECK_GT(buf_len, 0); | 
| 309 | 310 | 
| 310   TRACE_EVENT_BEGIN("socket.write", this, ""); | 311   TRACE_EVENT_BEGIN("socket.write", this, ""); | 
| 311   int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); | 312   int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); | 
| 312   if (nwrite >= 0) { | 313   if (nwrite >= 0) { | 
| 313     TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", nwrite)); | 314     TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", nwrite)); | 
|  | 315     net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_SENT, nwrite); | 
| 314     return nwrite; | 316     return nwrite; | 
| 315   } | 317   } | 
| 316   if (errno != EAGAIN && errno != EWOULDBLOCK) | 318   if (errno != EAGAIN && errno != EWOULDBLOCK) | 
| 317     return MapPosixError(errno); | 319     return MapPosixError(errno); | 
| 318 | 320 | 
| 319   if (!MessageLoopForIO::current()->WatchFileDescriptor( | 321   if (!MessageLoopForIO::current()->WatchFileDescriptor( | 
| 320           socket_, true, MessageLoopForIO::WATCH_WRITE, | 322           socket_, true, MessageLoopForIO::WATCH_WRITE, | 
| 321           &write_socket_watcher_, &write_watcher_)) { | 323           &write_socket_watcher_, &write_watcher_)) { | 
| 322     DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; | 324     DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; | 
| 323     return MapPosixError(errno); | 325     return MapPosixError(errno); | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 396     os_error = errno; | 398     os_error = errno; | 
| 397 | 399 | 
| 398   if (os_error == EINPROGRESS || os_error == EALREADY) { | 400   if (os_error == EINPROGRESS || os_error == EALREADY) { | 
| 399     NOTREACHED();  // This indicates a bug in libevent or our code. | 401     NOTREACHED();  // This indicates a bug in libevent or our code. | 
| 400     result = ERR_IO_PENDING; | 402     result = ERR_IO_PENDING; | 
| 401   } else if (current_ai_->ai_next && ShouldTryNextAddress(os_error)) { | 403   } else if (current_ai_->ai_next && ShouldTryNextAddress(os_error)) { | 
| 402     // This address failed, try next one in list. | 404     // This address failed, try next one in list. | 
| 403     const addrinfo* next = current_ai_->ai_next; | 405     const addrinfo* next = current_ai_->ai_next; | 
| 404     Disconnect(); | 406     Disconnect(); | 
| 405     current_ai_ = next; | 407     current_ai_ = next; | 
| 406     BoundNetLog net_log = net_log_; |  | 
| 407     net_log_ = BoundNetLog(); |  | 
| 408     TRACE_EVENT_END("socket.connect", this, ""); | 408     TRACE_EVENT_END("socket.connect", this, ""); | 
| 409     net_log.EndEvent(NetLog::TYPE_TCP_CONNECT); | 409     net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); | 
| 410     result = Connect(write_callback_, net_log); | 410     result = Connect(write_callback_); | 
| 411   } else { | 411   } else { | 
| 412     result = MapConnectError(os_error); | 412     result = MapConnectError(os_error); | 
| 413     bool ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 413     bool ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 
| 414     DCHECK(ok); | 414     DCHECK(ok); | 
| 415     waiting_connect_ = false; | 415     waiting_connect_ = false; | 
| 416     TRACE_EVENT_END("socket.connect", this, ""); | 416     TRACE_EVENT_END("socket.connect", this, ""); | 
| 417     net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); | 417     net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); | 
| 418     net_log_ = BoundNetLog(); |  | 
| 419   } | 418   } | 
| 420 | 419 | 
| 421   if (result != ERR_IO_PENDING) { | 420   if (result != ERR_IO_PENDING) { | 
| 422     DoWriteCallback(result); | 421     DoWriteCallback(result); | 
| 423   } | 422   } | 
| 424 } | 423 } | 
| 425 | 424 | 
| 426 void TCPClientSocketLibevent::DidCompleteRead() { | 425 void TCPClientSocketLibevent::DidCompleteRead() { | 
| 427   int bytes_transferred; | 426   int bytes_transferred; | 
| 428   bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), | 427   bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), | 
| 429                                         read_buf_len_)); | 428                                         read_buf_len_)); | 
| 430 | 429 | 
| 431   int result; | 430   int result; | 
| 432   if (bytes_transferred >= 0) { | 431   if (bytes_transferred >= 0) { | 
| 433     TRACE_EVENT_END("socket.read", this, | 432     TRACE_EVENT_END("socket.read", this, | 
| 434                     StringPrintf("%d bytes", bytes_transferred)); | 433                     StringPrintf("%d bytes", bytes_transferred)); | 
| 435     result = bytes_transferred; | 434     result = bytes_transferred; | 
|  | 435     net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_RECEIVED, result); | 
| 436   } else { | 436   } else { | 
| 437     result = MapPosixError(errno); | 437     result = MapPosixError(errno); | 
| 438   } | 438   } | 
| 439 | 439 | 
| 440   if (result != ERR_IO_PENDING) { | 440   if (result != ERR_IO_PENDING) { | 
| 441     read_buf_ = NULL; | 441     read_buf_ = NULL; | 
| 442     read_buf_len_ = 0; | 442     read_buf_len_ = 0; | 
| 443     bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 443     bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 
| 444     DCHECK(ok); | 444     DCHECK(ok); | 
| 445     DoReadCallback(result); | 445     DoReadCallback(result); | 
| 446   } | 446   } | 
| 447 } | 447 } | 
| 448 | 448 | 
| 449 void TCPClientSocketLibevent::DidCompleteWrite() { | 449 void TCPClientSocketLibevent::DidCompleteWrite() { | 
| 450   int bytes_transferred; | 450   int bytes_transferred; | 
| 451   bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), | 451   bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), | 
| 452                                          write_buf_len_)); | 452                                          write_buf_len_)); | 
| 453 | 453 | 
| 454   int result; | 454   int result; | 
| 455   if (bytes_transferred >= 0) { | 455   if (bytes_transferred >= 0) { | 
| 456     result = bytes_transferred; | 456     result = bytes_transferred; | 
| 457     TRACE_EVENT_END("socket.write", this, | 457     TRACE_EVENT_END("socket.write", this, | 
| 458                     StringPrintf("%d bytes", bytes_transferred)); | 458                     StringPrintf("%d bytes", bytes_transferred)); | 
|  | 459     net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_SENT, result); | 
| 459   } else { | 460   } else { | 
| 460     result = MapPosixError(errno); | 461     result = MapPosixError(errno); | 
| 461   } | 462   } | 
| 462 | 463 | 
| 463   if (result != ERR_IO_PENDING) { | 464   if (result != ERR_IO_PENDING) { | 
| 464     write_buf_ = NULL; | 465     write_buf_ = NULL; | 
| 465     write_buf_len_ = 0; | 466     write_buf_len_ = 0; | 
| 466     write_socket_watcher_.StopWatchingFileDescriptor(); | 467     write_socket_watcher_.StopWatchingFileDescriptor(); | 
| 467     DoWriteCallback(result); | 468     DoWriteCallback(result); | 
| 468   } | 469   } | 
| 469 } | 470 } | 
| 470 | 471 | 
| 471 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { | 472 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { | 
| 472   DCHECK(address); | 473   DCHECK(address); | 
| 473   if (!current_ai_) | 474   if (!current_ai_) | 
| 474     return ERR_UNEXPECTED; | 475     return ERR_UNEXPECTED; | 
| 475   address->Copy(current_ai_, false); | 476   address->Copy(current_ai_, false); | 
| 476   return OK; | 477   return OK; | 
| 477 } | 478 } | 
| 478 | 479 | 
| 479 }  // namespace net | 480 }  // namespace net | 
| OLD | NEW | 
|---|