Chromium Code Reviews| 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 #include "build/build_config.h" | 5 #include "build/build_config.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 // winsock2.h must be included first in order to ensure it is included before | 8 // winsock2.h must be included first in order to ensure it is included before |
| 9 // windows.h. | 9 // windows.h. |
| 10 #include <winsock2.h> | 10 #include <winsock2.h> |
| 11 #elif defined(OS_POSIX) | 11 #elif defined(OS_POSIX) |
| 12 #include <errno.h> | 12 #include <errno.h> |
| 13 #include <sys/types.h> | 13 #include <sys/types.h> |
| 14 #include <sys/socket.h> | 14 #include <sys/socket.h> |
| 15 #include <netinet/in.h> | 15 #include <netinet/in.h> |
| 16 #include <arpa/inet.h> | 16 #include <arpa/inet.h> |
| 17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 #endif | 18 #endif |
| 19 | 19 |
| 20 #include "base/bind.h" | |
| 20 #include "base/eintr_wrapper.h" | 21 #include "base/eintr_wrapper.h" |
| 21 #include "base/sys_byteorder.h" | 22 #include "base/sys_byteorder.h" |
| 22 #include "base/threading/platform_thread.h" | 23 #include "base/threading/platform_thread.h" |
| 23 #include "net/base/net_util.h" | 24 #include "net/base/net_util.h" |
| 24 #include "net/base/tcp_listen_socket.h" | 25 #include "net/base/tcp_listen_socket.h" |
| 25 | 26 |
| 26 #if defined(OS_WIN) | 27 #if defined(OS_WIN) |
| 27 typedef int socklen_t; | 28 typedef int socklen_t; |
| 29 #include "net/base/winsock_init.h" | |
| 28 #endif // defined(OS_WIN) | 30 #endif // defined(OS_WIN) |
| 29 | 31 |
| 30 namespace net { | 32 namespace net { |
| 31 | 33 |
| 32 namespace { | 34 namespace { |
| 33 | 35 |
| 34 const int kReadBufSize = 4096; | 36 const int kReadBufSize = 4096; |
| 37 const int kMaxSendBufSize = 1024*1024*5; // 5MB | |
| 38 | |
| 39 const net::BackoffEntry::Policy kSendDataBackoffPolicy = { | |
| 40 // Number of initial errors (in sequence) to ignore before applying | |
| 41 // exponential back-off rules. | |
| 42 0, | |
| 43 | |
| 44 // Initial delay for exponential back-off in ms. | |
| 45 100, | |
|
mmenke
2012/05/08 21:23:38
If we're sending megabytes locally, 100 millisecon
Marshall
2012/05/08 21:44:51
Reduced to 25ms.
| |
| 46 | |
| 47 // Factor by which the waiting time will be multiplied. | |
| 48 2, | |
| 49 | |
| 50 // Fuzzing percentage. ex: 10% will spread requests randomly | |
| 51 // between 90%-100% of the calculated time. | |
| 52 0, | |
| 53 | |
| 54 // Maximum amount of time we are willing to delay our request in ms. | |
| 55 500, | |
| 56 | |
| 57 // Time to keep an entry from being discarded even when it | |
| 58 // has no significant state, -1 to never discard. | |
| 59 -1, | |
| 60 | |
| 61 // Don't use initial delay unless the last request was an error. | |
| 62 false, | |
| 63 }; | |
| 35 | 64 |
| 36 } // namespace | 65 } // namespace |
| 37 | 66 |
| 38 #if defined(OS_WIN) | 67 #if defined(OS_WIN) |
| 39 const SOCKET TCPListenSocket::kInvalidSocket = INVALID_SOCKET; | 68 const SOCKET TCPListenSocket::kInvalidSocket = INVALID_SOCKET; |
| 40 const int TCPListenSocket::kSocketError = SOCKET_ERROR; | 69 const int TCPListenSocket::kSocketError = SOCKET_ERROR; |
| 41 #elif defined(OS_POSIX) | 70 #elif defined(OS_POSIX) |
| 42 const SOCKET TCPListenSocket::kInvalidSocket = -1; | 71 const SOCKET TCPListenSocket::kInvalidSocket = -1; |
| 43 const int TCPListenSocket::kSocketError = -1; | 72 const int TCPListenSocket::kSocketError = -1; |
| 44 #endif | 73 #endif |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 68 has_pending_reads_ = false; | 97 has_pending_reads_ = false; |
| 69 Read(); | 98 Read(); |
| 70 } | 99 } |
| 71 } | 100 } |
| 72 | 101 |
| 73 TCPListenSocket::TCPListenSocket(SOCKET s, | 102 TCPListenSocket::TCPListenSocket(SOCKET s, |
| 74 ListenSocket::ListenSocketDelegate *del) | 103 ListenSocket::ListenSocketDelegate *del) |
| 75 : ListenSocket(del), | 104 : ListenSocket(del), |
| 76 socket_(s), | 105 socket_(s), |
| 77 reads_paused_(false), | 106 reads_paused_(false), |
| 78 has_pending_reads_(false) { | 107 has_pending_reads_(false), |
| 108 send_data_error_(false), | |
| 109 send_data_backoff_(&kSendDataBackoffPolicy) { | |
| 79 #if defined(OS_WIN) | 110 #if defined(OS_WIN) |
| 80 socket_event_ = WSACreateEvent(); | 111 socket_event_ = WSACreateEvent(); |
| 81 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT | 112 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT |
| 82 WatchSocket(NOT_WAITING); | 113 WatchSocket(NOT_WAITING); |
| 83 #elif defined(OS_POSIX) | 114 #elif defined(OS_POSIX) |
| 84 wait_state_ = NOT_WAITING; | 115 wait_state_ = NOT_WAITING; |
| 85 #endif | 116 #endif |
| 86 } | 117 } |
| 87 | 118 |
| 88 TCPListenSocket::~TCPListenSocket() { | 119 TCPListenSocket::~TCPListenSocket() { |
| 89 #if defined(OS_WIN) | 120 #if defined(OS_WIN) |
| 90 if (socket_event_) { | 121 if (socket_event_) { |
| 91 WSACloseEvent(socket_event_); | 122 WSACloseEvent(socket_event_); |
| 92 socket_event_ = WSA_INVALID_EVENT; | 123 socket_event_ = WSA_INVALID_EVENT; |
| 93 } | 124 } |
| 94 #endif | 125 #endif |
| 95 CloseSocket(socket_); | 126 CloseSocket(socket_); |
| 96 } | 127 } |
| 97 | 128 |
| 98 SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) { | 129 SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) { |
| 130 #if defined(OS_WIN) | |
| 131 EnsureWinsockInit(); | |
| 132 #endif | |
| 133 | |
| 99 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | 134 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 100 if (s != kInvalidSocket) { | 135 if (s != kInvalidSocket) { |
| 101 #if defined(OS_POSIX) | 136 #if defined(OS_POSIX) |
| 102 // Allow rapid reuse. | 137 // Allow rapid reuse. |
| 103 static const int kOn = 1; | 138 static const int kOn = 1; |
| 104 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); | 139 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); |
| 105 #endif | 140 #endif |
| 106 sockaddr_in addr; | 141 sockaddr_in addr; |
| 107 memset(&addr, 0, sizeof(addr)); | 142 memset(&addr, 0, sizeof(addr)); |
| 108 addr.sin_family = AF_INET; | 143 addr.sin_family = AF_INET; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 125 socklen_t from_len = sizeof(from); | 160 socklen_t from_len = sizeof(from); |
| 126 SOCKET conn = | 161 SOCKET conn = |
| 127 HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len)); | 162 HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len)); |
| 128 if (conn != kInvalidSocket) { | 163 if (conn != kInvalidSocket) { |
| 129 SetNonBlocking(conn); | 164 SetNonBlocking(conn); |
| 130 } | 165 } |
| 131 return conn; | 166 return conn; |
| 132 } | 167 } |
| 133 | 168 |
| 134 void TCPListenSocket::SendInternal(const char* bytes, int len) { | 169 void TCPListenSocket::SendInternal(const char* bytes, int len) { |
| 135 char* send_buf = const_cast<char *>(bytes); | 170 DCHECK(bytes); |
| 136 int len_left = len; | 171 DCHECK_GT(len, 0); |
| 137 while (true) { | 172 |
| 138 int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0)); | 173 if (send_data_error_) |
| 139 if (sent == len_left) { // A shortcut to avoid extraneous checks. | 174 return; |
| 140 break; | 175 |
| 141 } | 176 // Add all bytes to the send buffer. |
| 142 if (sent == kSocketError) { | 177 if (send_data_.empty()) { |
| 143 #if defined(OS_WIN) | 178 send_data_.assign(bytes, len); |
| 144 if (WSAGetLastError() != WSAEWOULDBLOCK) { | 179 } else if (send_data_.size() > kMaxSendBufSize) { |
|
mmenke
2012/05/08 20:51:43
Should this be send_data_.size() + len? We'd stil
Marshall
2012/05/08 21:44:51
Done.
| |
| 145 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); | 180 // Too much of a backup, stop trying to add more data. |
| 146 #elif defined(OS_POSIX) | 181 LOG(ERROR) << "send failed: buffer overrun"; |
| 147 if (errno != EWOULDBLOCK && errno != EAGAIN) { | 182 send_data_error_ = true; |
|
mmenke
2012/05/08 20:51:43
send_data_.clear()?
Marshall
2012/05/08 21:44:51
Done.
| |
| 148 LOG(ERROR) << "send failed: errno==" << errno; | 183 return; |
| 149 #endif | 184 } else { |
| 150 break; | 185 send_data_.append(bytes, len); |
| 151 } | |
| 152 // Otherwise we would block, and now we have to wait for a retry. | |
| 153 // Fall through to PlatformThread::YieldCurrentThread() | |
| 154 } else { | |
| 155 // sent != len_left according to the shortcut above. | |
| 156 // Shift the buffer start and send the remainder after a short while. | |
| 157 send_buf += sent; | |
| 158 len_left -= sent; | |
| 159 } | |
| 160 base::PlatformThread::YieldCurrentThread(); | |
| 161 } | 186 } |
| 187 | |
| 188 if (!send_data_backoff_.ShouldRejectRequest()) | |
| 189 SendData(); | |
| 162 } | 190 } |
| 163 | 191 |
| 164 void TCPListenSocket::Listen() { | 192 void TCPListenSocket::Listen() { |
| 165 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? | 193 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? |
| 166 listen(socket_, backlog); | 194 listen(socket_, backlog); |
| 167 // TODO(erikkay): error handling | 195 // TODO(erikkay): error handling |
| 168 #if defined(OS_POSIX) | 196 #if defined(OS_POSIX) |
| 169 WatchSocket(WAITING_ACCEPT); | 197 WatchSocket(WAITING_ACCEPT); |
| 170 #endif | 198 #endif |
| 171 } | 199 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 } | 340 } |
| 313 | 341 |
| 314 void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { | 342 void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { |
| 315 // MessagePumpLibevent callback, we don't listen for write events | 343 // MessagePumpLibevent callback, we don't listen for write events |
| 316 // so we shouldn't ever reach here. | 344 // so we shouldn't ever reach here. |
| 317 NOTREACHED(); | 345 NOTREACHED(); |
| 318 } | 346 } |
| 319 | 347 |
| 320 #endif | 348 #endif |
| 321 | 349 |
| 350 void TCPListenSocket::SendData() { | |
| 351 // Another send call may have already emptied the buffer. | |
| 352 if (send_data_.empty()) | |
| 353 return; | |
| 354 | |
| 355 int len_left = static_cast<int>(send_data_.length()); | |
| 356 int sent = HANDLE_EINTR(send(socket_, send_data_.c_str(), len_left, 0)); | |
| 357 if (sent == len_left) { | |
| 358 // All data has been sent. | |
| 359 send_data_.clear(); | |
| 360 | |
| 361 // Successfully sending all data clears the backoff state. | |
| 362 send_data_backoff_.Reset(); | |
| 363 return; | |
| 364 } | |
| 365 | |
| 366 if (sent == kSocketError) { | |
| 367 #if defined(OS_WIN) | |
| 368 if (WSAGetLastError() != WSAEWOULDBLOCK) { | |
| 369 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); | |
| 370 #elif defined(OS_POSIX) | |
| 371 if (errno != EWOULDBLOCK && errno != EAGAIN) { | |
| 372 LOG(ERROR) << "send failed: errno==" << errno; | |
| 373 #endif | |
| 374 // Don't try to re-send data after a socket error. | |
| 375 send_data_.clear(); | |
| 376 send_data_error_ = true; | |
| 377 return; | |
| 378 } | |
| 379 | |
| 380 // Blocking is considered a failure. | |
| 381 send_data_backoff_.InformOfRequest(false); | |
| 382 } | |
| 383 | |
| 384 if (sent > 0) { | |
| 385 // Remove the sent bytes from the buffer. | |
| 386 send_data_ = send_data_.substr(sent, len_left - sent); | |
| 387 | |
| 388 // Sending any data is considered a success. | |
| 389 send_data_backoff_.InformOfRequest(true); | |
| 390 } | |
| 391 | |
| 392 if (!send_timer_.IsRunning()) { | |
| 393 // Schedule a timer to continue sending data asynchronously. | |
| 394 send_timer_.Start(FROM_HERE, send_data_backoff_.GetTimeUntilRelease(), | |
| 395 this, &TCPListenSocket::SendData); | |
| 396 } | |
| 397 } | |
| 398 | |
| 322 } // namespace net | 399 } // namespace net |
| OLD | NEW |