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 "net/base/tcp_listen_socket.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/logging.h" |
21 #include "base/eintr_wrapper.h" | |
22 #include "base/sys_byteorder.h" | 21 #include "base/sys_byteorder.h" |
23 #include "base/threading/platform_thread.h" | 22 #include "base/threading/platform_thread.h" |
| 23 #include "build/build_config.h" |
24 #include "net/base/net_util.h" | 24 #include "net/base/net_util.h" |
25 #include "net/base/tcp_listen_socket.h" | 25 #include "net/base/winsock_init.h" |
26 | 26 |
27 #if defined(OS_WIN) | 27 using std::string; |
28 typedef int socklen_t; | |
29 #include "net/base/winsock_init.h" | |
30 #endif // defined(OS_WIN) | |
31 | 28 |
32 namespace net { | 29 namespace net { |
33 | 30 |
34 namespace { | 31 // static |
35 | 32 scoped_refptr<TCPListenSocket> TCPListenSocket::CreateAndListen( |
36 const int kReadBufSize = 4096; | 33 const string& ip, int port, StreamListenSocket::Delegate* del) { |
37 const int kMaxSendBufSize = 1024 * 1024 * 5; // 5MB | |
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 }; | |
64 | |
65 } // namespace | |
66 | |
67 #if defined(OS_WIN) | |
68 const SOCKET TCPListenSocket::kInvalidSocket = INVALID_SOCKET; | |
69 const int TCPListenSocket::kSocketError = SOCKET_ERROR; | |
70 #elif defined(OS_POSIX) | |
71 const SOCKET TCPListenSocket::kInvalidSocket = -1; | |
72 const int TCPListenSocket::kSocketError = -1; | |
73 #endif | |
74 | |
75 TCPListenSocket* TCPListenSocket::CreateAndListen( | |
76 const std::string& ip, int port, ListenSocket::ListenSocketDelegate *del) { | |
77 SOCKET s = CreateAndBind(ip, port); | 34 SOCKET s = CreateAndBind(ip, port); |
78 if (s == kInvalidSocket) { | 35 if (s == kInvalidSocket) |
79 // TODO(erikkay): error handling | 36 return NULL; |
80 } else { | 37 scoped_refptr<TCPListenSocket> sock(new TCPListenSocket(s, del)); |
81 TCPListenSocket* sock = new TCPListenSocket(s, del); | 38 sock->Listen(); |
82 sock->Listen(); | 39 return sock; |
83 return sock; | |
84 } | |
85 return NULL; | |
86 } | 40 } |
87 | 41 |
88 void TCPListenSocket::PauseReads() { | 42 TCPListenSocket::TCPListenSocket(SOCKET s, StreamListenSocket::Delegate* del) |
89 DCHECK(!reads_paused_); | 43 : StreamListenSocket(s, del) { |
90 reads_paused_ = true; | |
91 } | 44 } |
92 | 45 |
93 void TCPListenSocket::ResumeReads() { | 46 TCPListenSocket::~TCPListenSocket() {} |
94 DCHECK(reads_paused_); | |
95 reads_paused_ = false; | |
96 if (has_pending_reads_) { | |
97 has_pending_reads_ = false; | |
98 Read(); | |
99 } | |
100 } | |
101 | 47 |
102 TCPListenSocket::TCPListenSocket(SOCKET s, | 48 SOCKET TCPListenSocket::CreateAndBind(const string& ip, int port) { |
103 ListenSocket::ListenSocketDelegate *del) | |
104 : ListenSocket(del), | |
105 socket_(s), | |
106 reads_paused_(false), | |
107 has_pending_reads_(false), | |
108 send_pending_size_(0), | |
109 send_error_(false), | |
110 send_backoff_(&kSendBackoffPolicy) { | |
111 #if defined(OS_WIN) | |
112 socket_event_ = WSACreateEvent(); | |
113 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT | |
114 WatchSocket(NOT_WAITING); | |
115 #elif defined(OS_POSIX) | |
116 wait_state_ = NOT_WAITING; | |
117 #endif | |
118 } | |
119 | |
120 TCPListenSocket::~TCPListenSocket() { | |
121 #if defined(OS_WIN) | |
122 if (socket_event_) { | |
123 WSACloseEvent(socket_event_); | |
124 socket_event_ = WSA_INVALID_EVENT; | |
125 } | |
126 #endif | |
127 CloseSocket(socket_); | |
128 } | |
129 | |
130 SOCKET TCPListenSocket::CreateAndBind(const std::string& ip, int port) { | |
131 #if defined(OS_WIN) | 49 #if defined(OS_WIN) |
132 EnsureWinsockInit(); | 50 EnsureWinsockInit(); |
133 #endif | 51 #endif |
134 | 52 |
135 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | 53 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
136 if (s != kInvalidSocket) { | 54 if (s != kInvalidSocket) { |
137 #if defined(OS_POSIX) | 55 #if defined(OS_POSIX) |
138 // Allow rapid reuse. | 56 // Allow rapid reuse. |
139 static const int kOn = 1; | 57 static const int kOn = 1; |
140 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); | 58 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); |
141 #endif | 59 #endif |
142 sockaddr_in addr; | 60 sockaddr_in addr; |
143 memset(&addr, 0, sizeof(addr)); | 61 memset(&addr, 0, sizeof(addr)); |
144 addr.sin_family = AF_INET; | 62 addr.sin_family = AF_INET; |
145 addr.sin_addr.s_addr = inet_addr(ip.c_str()); | 63 addr.sin_addr.s_addr = inet_addr(ip.c_str()); |
146 addr.sin_port = base::HostToNet16(port); | 64 addr.sin_port = base::HostToNet16(port); |
147 if (bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) { | 65 if (bind(s, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) { |
148 #if defined(OS_WIN) | 66 #if defined(OS_WIN) |
149 closesocket(s); | 67 closesocket(s); |
150 #elif defined(OS_POSIX) | 68 #elif defined(OS_POSIX) |
151 close(s); | 69 close(s); |
152 #endif | 70 #endif |
| 71 LOG(ERROR) << "Could not bind socket to " << ip << ":" << port; |
153 s = kInvalidSocket; | 72 s = kInvalidSocket; |
154 } | 73 } |
155 } | 74 } |
156 return s; | 75 return s; |
157 } | 76 } |
158 | 77 |
159 SOCKET TCPListenSocket::Accept(SOCKET s) { | 78 void TCPListenSocket::Accept() { |
160 sockaddr_in from; | 79 SOCKET conn = AcceptSocket(); |
161 socklen_t from_len = sizeof(from); | 80 if (conn == kInvalidSocket) |
162 SOCKET conn = | |
163 HANDLE_EINTR(accept(s, reinterpret_cast<sockaddr*>(&from), &from_len)); | |
164 if (conn != kInvalidSocket) { | |
165 SetNonBlocking(conn); | |
166 } | |
167 return conn; | |
168 } | |
169 | |
170 void TCPListenSocket::SendInternal(const char* bytes, int len) { | |
171 DCHECK(bytes); | |
172 if (!bytes || len <= 0) | |
173 return; | 81 return; |
174 | 82 scoped_refptr<TCPListenSocket> sock( |
175 if (send_error_) | 83 new TCPListenSocket(conn, socket_delegate_)); |
176 return; | 84 // It's up to the delegate to AddRef if it wants to keep it around. |
177 | |
178 if (send_pending_size_ + len > kMaxSendBufSize) { | |
179 LOG(ERROR) << "send failed: buffer overrun"; | |
180 send_buffers_.clear(); | |
181 send_pending_size_ = 0; | |
182 send_error_ = true; | |
183 return; | |
184 } | |
185 | |
186 scoped_refptr<IOBuffer> buffer(new IOBuffer(len)); | |
187 memcpy(buffer->data(), bytes, len); | |
188 send_buffers_.push_back(new DrainableIOBuffer(buffer, len)); | |
189 send_pending_size_ += len; | |
190 | |
191 if (!send_timer_.IsRunning()) | |
192 SendData(); | |
193 } | |
194 | |
195 void TCPListenSocket::Listen() { | |
196 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? | |
197 listen(socket_, backlog); | |
198 // TODO(erikkay): error handling | |
199 #if defined(OS_POSIX) | 85 #if defined(OS_POSIX) |
200 WatchSocket(WAITING_ACCEPT); | 86 sock->WatchSocket(WAITING_READ); |
201 #endif | 87 #endif |
202 } | 88 socket_delegate_->DidAccept(this, sock); |
203 | |
204 void TCPListenSocket::Accept() { | |
205 SOCKET conn = Accept(socket_); | |
206 if (conn != kInvalidSocket) { | |
207 scoped_refptr<TCPListenSocket> sock( | |
208 new TCPListenSocket(conn, socket_delegate_)); | |
209 // it's up to the delegate to AddRef if it wants to keep it around | |
210 #if defined(OS_POSIX) | |
211 sock->WatchSocket(WAITING_READ); | |
212 #endif | |
213 socket_delegate_->DidAccept(this, sock); | |
214 } else { | |
215 // TODO(ibrar): some error handling required here | |
216 } | |
217 } | |
218 | |
219 void TCPListenSocket::Read() { | |
220 char buf[kReadBufSize + 1]; // +1 for null termination | |
221 int len; | |
222 do { | |
223 len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0)); | |
224 if (len == kSocketError) { | |
225 #if defined(OS_WIN) | |
226 int err = WSAGetLastError(); | |
227 if (err == WSAEWOULDBLOCK) { | |
228 #elif defined(OS_POSIX) | |
229 if (errno == EWOULDBLOCK || errno == EAGAIN) { | |
230 #endif | |
231 break; | |
232 } else { | |
233 // TODO(ibrar): some error handling required here | |
234 break; | |
235 } | |
236 } else if (len == 0) { | |
237 // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need | |
238 // to call it here. | |
239 #if defined(OS_POSIX) | |
240 Close(); | |
241 #endif | |
242 } else { | |
243 // TODO(ibrar): maybe change DidRead to take a length instead | |
244 DCHECK_GT(len, 0); | |
245 DCHECK_LE(len, kReadBufSize); | |
246 buf[len] = 0; // already create a buffer with +1 length | |
247 socket_delegate_->DidRead(this, buf, len); | |
248 } | |
249 } while (len == kReadBufSize); | |
250 } | |
251 | |
252 void TCPListenSocket::Close() { | |
253 #if defined(OS_POSIX) | |
254 if (wait_state_ == NOT_WAITING) | |
255 return; | |
256 wait_state_ = NOT_WAITING; | |
257 #endif | |
258 UnwatchSocket(); | |
259 socket_delegate_->DidClose(this); | |
260 } | |
261 | |
262 void TCPListenSocket::CloseSocket(SOCKET s) { | |
263 if (s && s != kInvalidSocket) { | |
264 UnwatchSocket(); | |
265 #if defined(OS_WIN) | |
266 closesocket(s); | |
267 #elif defined(OS_POSIX) | |
268 close(s); | |
269 #endif | |
270 } | |
271 } | |
272 | |
273 void TCPListenSocket::WatchSocket(WaitState state) { | |
274 #if defined(OS_WIN) | |
275 WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ); | |
276 watcher_.StartWatching(socket_event_, this); | |
277 #elif defined(OS_POSIX) | |
278 // Implicitly calls StartWatchingFileDescriptor(). | |
279 MessageLoopForIO::current()->WatchFileDescriptor( | |
280 socket_, true, MessageLoopForIO::WATCH_READ, &watcher_, this); | |
281 wait_state_ = state; | |
282 #endif | |
283 } | |
284 | |
285 void TCPListenSocket::UnwatchSocket() { | |
286 #if defined(OS_WIN) | |
287 watcher_.StopWatching(); | |
288 #elif defined(OS_POSIX) | |
289 watcher_.StopWatchingFileDescriptor(); | |
290 #endif | |
291 } | |
292 | |
293 // TODO(ibrar): We can add these functions into OS dependent files | |
294 #if defined(OS_WIN) | |
295 // MessageLoop watcher callback | |
296 void TCPListenSocket::OnObjectSignaled(HANDLE object) { | |
297 WSANETWORKEVENTS ev; | |
298 if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) { | |
299 // TODO | |
300 return; | |
301 } | |
302 | |
303 // The object was reset by WSAEnumNetworkEvents. Watch for the next signal. | |
304 watcher_.StartWatching(object, this); | |
305 | |
306 if (ev.lNetworkEvents == 0) { | |
307 // Occasionally the event is set even though there is no new data. | |
308 // The net seems to think that this is ignorable. | |
309 return; | |
310 } | |
311 if (ev.lNetworkEvents & FD_ACCEPT) { | |
312 Accept(); | |
313 } | |
314 if (ev.lNetworkEvents & FD_READ) { | |
315 if (reads_paused_) { | |
316 has_pending_reads_ = true; | |
317 } else { | |
318 Read(); | |
319 } | |
320 } | |
321 if (ev.lNetworkEvents & FD_CLOSE) { | |
322 Close(); | |
323 } | |
324 } | |
325 #elif defined(OS_POSIX) | |
326 void TCPListenSocket::OnFileCanReadWithoutBlocking(int fd) { | |
327 switch (wait_state_) { | |
328 case WAITING_ACCEPT: | |
329 Accept(); | |
330 break; | |
331 case WAITING_READ: | |
332 if (reads_paused_) { | |
333 has_pending_reads_ = true; | |
334 } else { | |
335 Read(); | |
336 } | |
337 break; | |
338 default: | |
339 // Close() is called by Read() in the Linux case. | |
340 NOTREACHED(); | |
341 break; | |
342 } | |
343 } | |
344 | |
345 void TCPListenSocket::OnFileCanWriteWithoutBlocking(int fd) { | |
346 // MessagePumpLibevent callback, we don't listen for write events | |
347 // so we shouldn't ever reach here. | |
348 NOTREACHED(); | |
349 } | |
350 | |
351 #endif | |
352 | |
353 void TCPListenSocket::SendData() { | |
354 DCHECK(!send_buffers_.empty()); | |
355 | |
356 int total_sent = 0; | |
357 | |
358 // Send data until all buffers have been sent or a call would block. | |
359 while (!send_buffers_.empty()) { | |
360 scoped_refptr<DrainableIOBuffer> buffer = send_buffers_.front(); | |
361 | |
362 int len_left = buffer->BytesRemaining(); | |
363 int sent = HANDLE_EINTR(send(socket_, buffer->data(), len_left, 0)); | |
364 if (sent > 0) { | |
365 if (sent == len_left) | |
366 send_buffers_.pop_front(); | |
367 else | |
368 buffer->DidConsume(sent); | |
369 | |
370 total_sent += sent; | |
371 } else if (sent == kSocketError) { | |
372 #if defined(OS_WIN) | |
373 if (WSAGetLastError() != WSAEWOULDBLOCK) { | |
374 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); | |
375 #elif defined(OS_POSIX) | |
376 if (errno != EWOULDBLOCK && errno != EAGAIN) { | |
377 LOG(ERROR) << "send failed: errno==" << errno; | |
378 #endif | |
379 // Don't try to re-send data after a socket error. | |
380 send_buffers_.clear(); | |
381 send_pending_size_ = 0; | |
382 send_error_ = true; | |
383 return; | |
384 } | |
385 | |
386 // The call would block. Don't send any more data at this time. | |
387 break; | |
388 } else { | |
389 NOTREACHED(); | |
390 break; | |
391 } | |
392 } | |
393 | |
394 if (total_sent > 0) { | |
395 send_pending_size_ -= total_sent; | |
396 DCHECK_GE(send_pending_size_, 0); | |
397 | |
398 // Clear the back-off delay. | |
399 send_backoff_.Reset(); | |
400 } else { | |
401 // Increase the back-off delay. | |
402 send_backoff_.InformOfRequest(false); | |
403 } | |
404 | |
405 if (!send_buffers_.empty()) { | |
406 DCHECK(!send_timer_.IsRunning()); | |
407 send_timer_.Start(FROM_HERE, send_backoff_.GetTimeUntilRelease(), | |
408 this, &TCPListenSocket::SendData); | |
409 } | |
410 } | 89 } |
411 | 90 |
412 } // namespace net | 91 } // namespace net |
OLD | NEW |