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 | |
mmenke
2012/05/09 19:20:08
nit: 1024 * 1024 * 5
Marshall
2012/05/10 16:28:05
Done.
| |
38 | |
39 const net::BackoffEntry::Policy kSendBackoffPolicy = { | |
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 25, | |
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 100, | |
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_pending_size_(0), | |
109 send_error_(false), | |
110 send_backoff_(&kSendBackoffPolicy) { | |
79 #if defined(OS_WIN) | 111 #if defined(OS_WIN) |
80 socket_event_ = WSACreateEvent(); | 112 socket_event_ = WSACreateEvent(); |
81 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT | 113 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT |
82 WatchSocket(NOT_WAITING); | 114 WatchSocket(NOT_WAITING); |
83 #elif defined(OS_POSIX) | 115 #elif defined(OS_POSIX) |
84 wait_state_ = NOT_WAITING; | 116 wait_state_ = NOT_WAITING; |
85 #endif | 117 #endif |
86 } | 118 } |
87 | 119 |
88 TCPListenSocket::~TCPListenSocket() { | 120 TCPListenSocket::~TCPListenSocket() { |
89 #if defined(OS_WIN) | 121 #if defined(OS_WIN) |
90 if (socket_event_) { | 122 if (socket_event_) { |
91 WSACloseEvent(socket_event_); | 123 WSACloseEvent(socket_event_); |
92 socket_event_ = WSA_INVALID_EVENT; | 124 socket_event_ = WSA_INVALID_EVENT; |
93 } | 125 } |
94 #endif | 126 #endif |
95 CloseSocket(socket_); | 127 CloseSocket(socket_); |
96 } | 128 } |
97 | 129 |
98 SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) { | 130 SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) { |
131 #if defined(OS_WIN) | |
132 EnsureWinsockInit(); | |
133 #endif | |
134 | |
99 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | 135 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
100 if (s != kInvalidSocket) { | 136 if (s != kInvalidSocket) { |
101 #if defined(OS_POSIX) | 137 #if defined(OS_POSIX) |
102 // Allow rapid reuse. | 138 // Allow rapid reuse. |
103 static const int kOn = 1; | 139 static const int kOn = 1; |
104 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); | 140 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); |
105 #endif | 141 #endif |
106 sockaddr_in addr; | 142 sockaddr_in addr; |
107 memset(&addr, 0, sizeof(addr)); | 143 memset(&addr, 0, sizeof(addr)); |
108 addr.sin_family = AF_INET; | 144 addr.sin_family = AF_INET; |
(...skipping 16 matching lines...) Expand all Loading... | |
125 socklen_t from_len = sizeof(from); | 161 socklen_t from_len = sizeof(from); |
126 SOCKET conn = | 162 SOCKET conn = |
127 HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len)); | 163 HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len)); |
128 if (conn != kInvalidSocket) { | 164 if (conn != kInvalidSocket) { |
129 SetNonBlocking(conn); | 165 SetNonBlocking(conn); |
130 } | 166 } |
131 return conn; | 167 return conn; |
132 } | 168 } |
133 | 169 |
134 void TCPListenSocket::SendInternal(const char* bytes, int len) { | 170 void TCPListenSocket::SendInternal(const char* bytes, int len) { |
135 char* send_buf = const_cast<char *>(bytes); | 171 DCHECK(bytes); |
136 int len_left = len; | 172 DCHECK_GT(len, 0); |
137 while (true) { | 173 |
138 int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0)); | 174 if (send_error_) |
139 if (sent == len_left) { // A shortcut to avoid extraneous checks. | 175 return; |
140 break; | 176 |
141 } | 177 if (send_pending_size_ + len > kMaxSendBufSize) { |
142 if (sent == kSocketError) { | 178 // Too much of a backup, stop trying to add more data. |
143 #if defined(OS_WIN) | 179 LOG(ERROR) << "send failed: buffer overrun"; |
144 if (WSAGetLastError() != WSAEWOULDBLOCK) { | 180 send_buffers_.clear(); |
145 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); | 181 send_pending_size_ = 0; |
146 #elif defined(OS_POSIX) | 182 send_error_ = true; |
147 if (errno != EWOULDBLOCK && errno != EAGAIN) { | 183 return; |
148 LOG(ERROR) << "send failed: errno==" << errno; | |
149 #endif | |
150 break; | |
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 } | 184 } |
185 | |
186 // Add a new buffer to the send buffer list. | |
187 scoped_refptr<IOBuffer> buffer(new IOBuffer(len)); | |
188 memcpy(buffer->data(), bytes, len); | |
189 send_buffers_.push_back(new DrainableIOBuffer(buffer, len)); | |
190 send_pending_size_ += len; | |
191 | |
192 if (!send_backoff_.ShouldRejectRequest()) | |
michaeln
2012/05/09 20:55:34
For clarity, consider replacing this test with !se
Marshall
2012/05/10 16:28:05
Done.
| |
193 SendData(); | |
162 } | 194 } |
163 | 195 |
164 void TCPListenSocket::Listen() { | 196 void TCPListenSocket::Listen() { |
165 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? | 197 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? |
166 listen(socket_, backlog); | 198 listen(socket_, backlog); |
167 // TODO(erikkay): error handling | 199 // TODO(erikkay): error handling |
168 #if defined(OS_POSIX) | 200 #if defined(OS_POSIX) |
169 WatchSocket(WAITING_ACCEPT); | 201 WatchSocket(WAITING_ACCEPT); |
170 #endif | 202 #endif |
171 } | 203 } |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 } | 344 } |
313 | 345 |
314 void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { | 346 void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { |
315 // MessagePumpLibevent callback, we don't listen for write events | 347 // MessagePumpLibevent callback, we don't listen for write events |
316 // so we shouldn't ever reach here. | 348 // so we shouldn't ever reach here. |
317 NOTREACHED(); | 349 NOTREACHED(); |
318 } | 350 } |
319 | 351 |
320 #endif | 352 #endif |
321 | 353 |
354 void TCPListenSocket::SendData() { | |
355 // Another send call may have already emptied the buffer list. | |
356 if (send_buffers_.empty()) | |
357 return; | |
358 | |
359 int total_sent = 0; | |
360 | |
361 // Send data until all buffers have been sent or a call would block. | |
362 do { | |
mmenke
2012/05/09 19:20:08
I think this may be a little simpler if you used a
Marshall
2012/05/10 16:28:05
Done.
| |
363 scoped_refptr<DrainableIOBuffer> buffer = send_buffers_.front(); | |
364 | |
365 int len_left = buffer->BytesRemaining(); | |
366 int sent = HANDLE_EINTR(send(socket_, buffer->data(), len_left, 0)); | |
367 if (sent == len_left) { | |
368 // All data has been sent. Remove the buffer from the list and move on | |
369 // to the next buffer, if any. | |
370 send_buffers_.erase(send_buffers_.begin()); | |
371 total_sent += sent; | |
372 continue; | |
373 } | |
374 | |
375 if (sent == kSocketError) { | |
michaeln
2012/05/09 20:55:34
Is it possible for send() to return any other erro
Marshall
2012/05/10 16:28:05
Done.
Marshall
2012/05/10 19:01:09
I changed this to an "else { NOTREACHED(); break;
| |
376 #if defined(OS_WIN) | |
377 if (WSAGetLastError() != WSAEWOULDBLOCK) { | |
378 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); | |
379 #elif defined(OS_POSIX) | |
380 if (errno != EWOULDBLOCK && errno != EAGAIN) { | |
381 LOG(ERROR) << "send failed: errno==" << errno; | |
382 #endif | |
383 // Don't try to re-send data after a socket error. | |
384 send_buffers_.clear(); | |
385 send_pending_size_ = 0; | |
386 send_error_ = true; | |
387 return; | |
388 } | |
389 | |
390 // The call would block. Don't send any more data at this time. | |
391 break; | |
392 } else if (sent > 0) { | |
michaeln
2012/05/09 20:55:34
nit: might be nice to have the sent everything and
Marshall
2012/05/10 16:28:05
Done.
| |
393 // The buffer was partially sent. | |
394 buffer->DidConsume(sent); | |
395 total_sent += sent; | |
396 } | |
397 } while (!send_buffers_.empty()); | |
398 | |
399 if (total_sent > 0) { | |
400 // Data has been sent. | |
michaeln
2012/05/09 20:55:34
nit: some of these comments are stating the obviou
Marshall
2012/05/10 16:28:05
I've removed some. Let me know if you think more s
| |
401 send_pending_size_ -= total_sent; | |
402 DCHECK_GE(send_pending_size_, 0); | |
403 | |
404 // Clear the back-off delay. | |
405 send_backoff_.Reset(); | |
406 } else { | |
407 // No data has been sent. Increase the back-off delay. | |
408 send_backoff_.InformOfRequest(false); | |
409 } | |
410 | |
411 if (!send_buffers_.empty() && !send_timer_.IsRunning()) { | |
412 // Schedule a timer to continue sending data asynchronously. | |
413 send_timer_.Start(FROM_HERE, send_backoff_.GetTimeUntilRelease(), | |
414 this, &TCPListenSocket::SendData); | |
415 } | |
416 } | |
417 | |
322 } // namespace net | 418 } // namespace net |
OLD | NEW |