OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/socket/stream_listen_socket.h" | |
6 | |
7 #if defined(OS_WIN) | |
8 // winsock2.h must be included first in order to ensure it is included before | |
9 // windows.h. | |
10 #include <winsock2.h> | |
11 #elif defined(OS_POSIX) | |
12 #include <arpa/inet.h> | |
13 #include <errno.h> | |
14 #include <netinet/in.h> | |
15 #include <sys/socket.h> | |
16 #include <sys/types.h> | |
17 #include "net/base/net_errors.h" | |
18 #endif | |
19 | |
20 #include "base/logging.h" | |
21 #include "base/memory/ref_counted.h" | |
22 #include "base/memory/scoped_ptr.h" | |
23 #include "base/posix/eintr_wrapper.h" | |
24 #include "base/profiler/scoped_tracker.h" | |
25 #include "base/sys_byteorder.h" | |
26 #include "base/threading/platform_thread.h" | |
27 #include "build/build_config.h" | |
28 #include "net/base/ip_endpoint.h" | |
29 #include "net/base/net_errors.h" | |
30 #include "net/base/net_util.h" | |
31 #include "net/socket/socket_descriptor.h" | |
32 | |
33 using std::string; | |
34 | |
35 #if defined(OS_WIN) | |
36 typedef int socklen_t; | |
37 #endif // defined(OS_WIN) | |
38 | |
39 namespace net { | |
40 | |
41 namespace { | |
42 | |
43 const int kReadBufSize = 4096; | |
44 | |
45 } // namespace | |
46 | |
47 #if defined(OS_WIN) | |
48 const int StreamListenSocket::kSocketError = SOCKET_ERROR; | |
49 #elif defined(OS_POSIX) | |
50 const int StreamListenSocket::kSocketError = -1; | |
51 #endif | |
52 | |
53 StreamListenSocket::StreamListenSocket(SocketDescriptor s, | |
54 StreamListenSocket::Delegate* del) | |
55 : socket_delegate_(del), | |
56 socket_(s), | |
57 reads_paused_(false), | |
58 has_pending_reads_(false) { | |
59 #if defined(OS_WIN) | |
60 socket_event_ = WSACreateEvent(); | |
61 // TODO(ibrar): error handling in case of socket_event_ == WSA_INVALID_EVENT. | |
62 WatchSocket(NOT_WAITING); | |
63 #elif defined(OS_POSIX) | |
64 wait_state_ = NOT_WAITING; | |
65 #endif | |
66 } | |
67 | |
68 StreamListenSocket::~StreamListenSocket() { | |
69 CloseSocket(); | |
70 #if defined(OS_WIN) | |
71 if (socket_event_) { | |
72 WSACloseEvent(socket_event_); | |
73 socket_event_ = WSA_INVALID_EVENT; | |
74 } | |
75 #endif | |
76 } | |
77 | |
78 void StreamListenSocket::Send(const char* bytes, int len, | |
79 bool append_linefeed) { | |
80 SendInternal(bytes, len); | |
81 if (append_linefeed) | |
82 SendInternal("\r\n", 2); | |
83 } | |
84 | |
85 void StreamListenSocket::Send(const string& str, bool append_linefeed) { | |
86 Send(str.data(), static_cast<int>(str.length()), append_linefeed); | |
87 } | |
88 | |
89 int StreamListenSocket::GetLocalAddress(IPEndPoint* address) { | |
90 SockaddrStorage storage; | |
91 if (getsockname(socket_, storage.addr, &storage.addr_len)) { | |
92 #if defined(OS_WIN) | |
93 int err = WSAGetLastError(); | |
94 #else | |
95 int err = errno; | |
96 #endif | |
97 return MapSystemError(err); | |
98 } | |
99 if (!address->FromSockAddr(storage.addr, storage.addr_len)) | |
100 return ERR_ADDRESS_INVALID; | |
101 return OK; | |
102 } | |
103 | |
104 int StreamListenSocket::GetPeerAddress(IPEndPoint* address) { | |
105 SockaddrStorage storage; | |
106 if (getpeername(socket_, storage.addr, &storage.addr_len)) { | |
107 #if defined(OS_WIN) | |
108 int err = WSAGetLastError(); | |
109 #else | |
110 int err = errno; | |
111 #endif | |
112 return MapSystemError(err); | |
113 } | |
114 | |
115 if (!address->FromSockAddr(storage.addr, storage.addr_len)) | |
116 return ERR_ADDRESS_INVALID; | |
117 | |
118 return OK; | |
119 } | |
120 | |
121 SocketDescriptor StreamListenSocket::AcceptSocket() { | |
122 SocketDescriptor conn = HANDLE_EINTR(accept(socket_, NULL, NULL)); | |
123 if (conn == kInvalidSocket) | |
124 LOG(ERROR) << "Error accepting connection."; | |
125 else | |
126 SetNonBlocking(conn); | |
127 return conn; | |
128 } | |
129 | |
130 void StreamListenSocket::SendInternal(const char* bytes, int len) { | |
131 char* send_buf = const_cast<char *>(bytes); | |
132 int len_left = len; | |
133 while (true) { | |
134 int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0)); | |
135 if (sent == len_left) { // A shortcut to avoid extraneous checks. | |
136 break; | |
137 } | |
138 if (sent == kSocketError) { | |
139 #if defined(OS_WIN) | |
140 if (WSAGetLastError() != WSAEWOULDBLOCK) { | |
141 LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError(); | |
142 #elif defined(OS_POSIX) | |
143 if (errno != EWOULDBLOCK && errno != EAGAIN) { | |
144 LOG(ERROR) << "send failed: errno==" << errno; | |
145 #endif | |
146 break; | |
147 } | |
148 // Otherwise we would block, and now we have to wait for a retry. | |
149 // Fall through to PlatformThread::YieldCurrentThread() | |
150 } else { | |
151 // sent != len_left according to the shortcut above. | |
152 // Shift the buffer start and send the remainder after a short while. | |
153 send_buf += sent; | |
154 len_left -= sent; | |
155 } | |
156 base::PlatformThread::YieldCurrentThread(); | |
157 } | |
158 } | |
159 | |
160 void StreamListenSocket::Listen() { | |
161 int backlog = 10; // TODO(erikkay): maybe don't allow any backlog? | |
162 if (listen(socket_, backlog) == -1) { | |
163 // TODO(erikkay): error handling. | |
164 LOG(ERROR) << "Could not listen on socket."; | |
165 return; | |
166 } | |
167 #if defined(OS_POSIX) | |
168 WatchSocket(WAITING_ACCEPT); | |
169 #endif | |
170 } | |
171 | |
172 void StreamListenSocket::Read() { | |
173 char buf[kReadBufSize + 1]; // +1 for null termination. | |
174 int len; | |
175 do { | |
176 len = HANDLE_EINTR(recv(socket_, buf, kReadBufSize, 0)); | |
177 if (len == kSocketError) { | |
178 #if defined(OS_WIN) | |
179 int err = WSAGetLastError(); | |
180 if (err == WSAEWOULDBLOCK) { | |
181 #elif defined(OS_POSIX) | |
182 if (errno == EWOULDBLOCK || errno == EAGAIN) { | |
183 #endif | |
184 break; | |
185 } else { | |
186 // TODO(ibrar): some error handling required here. | |
187 break; | |
188 } | |
189 } else if (len == 0) { | |
190 // In Windows, Close() is called by OnObjectSignaled. In POSIX, we need | |
191 // to call it here. | |
192 #if defined(OS_POSIX) | |
193 Close(); | |
194 #endif | |
195 } else { | |
196 // TODO(ibrar): maybe change DidRead to take a length instead. | |
197 DCHECK_GT(len, 0); | |
198 DCHECK_LE(len, kReadBufSize); | |
199 buf[len] = 0; // Already create a buffer with +1 length. | |
200 socket_delegate_->DidRead(this, buf, len); | |
201 } | |
202 } while (len == kReadBufSize); | |
203 } | |
204 | |
205 void StreamListenSocket::Close() { | |
206 #if defined(OS_POSIX) | |
207 if (wait_state_ == NOT_WAITING) | |
208 return; | |
209 wait_state_ = NOT_WAITING; | |
210 #endif | |
211 UnwatchSocket(); | |
212 socket_delegate_->DidClose(this); | |
213 } | |
214 | |
215 void StreamListenSocket::CloseSocket() { | |
216 if (socket_ != kInvalidSocket) { | |
217 UnwatchSocket(); | |
218 #if defined(OS_WIN) | |
219 closesocket(socket_); | |
220 #elif defined(OS_POSIX) | |
221 close(socket_); | |
222 #endif | |
223 } | |
224 } | |
225 | |
226 void StreamListenSocket::WatchSocket(WaitState state) { | |
227 #if defined(OS_WIN) | |
228 WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ); | |
229 watcher_.StartWatching(socket_event_, this); | |
230 #elif defined(OS_POSIX) | |
231 // Implicitly calls StartWatchingFileDescriptor(). | |
232 base::MessageLoopForIO::current()->WatchFileDescriptor( | |
233 socket_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this); | |
234 wait_state_ = state; | |
235 #endif | |
236 } | |
237 | |
238 void StreamListenSocket::UnwatchSocket() { | |
239 #if defined(OS_WIN) | |
240 watcher_.StopWatching(); | |
241 #elif defined(OS_POSIX) | |
242 watcher_.StopWatchingFileDescriptor(); | |
243 #endif | |
244 } | |
245 | |
246 // TODO(ibrar): We can add these functions into OS dependent files. | |
247 #if defined(OS_WIN) | |
248 // MessageLoop watcher callback. | |
249 void StreamListenSocket::OnObjectSignaled(HANDLE object) { | |
250 // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed. | |
251 tracked_objects::ScopedTracker tracking_profile( | |
252 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
253 "418183 StreamListenSocket::OnObjectSignaled")); | |
254 | |
255 WSANETWORKEVENTS ev; | |
256 if (kSocketError == WSAEnumNetworkEvents(socket_, socket_event_, &ev)) { | |
257 // TODO | |
258 return; | |
259 } | |
260 | |
261 // If both FD_CLOSE and FD_READ are set we only call Read(). | |
262 // This will cause OnObjectSignaled to be called immediately again | |
263 // unless this socket is destroyed in Read(). | |
264 if ((ev.lNetworkEvents & (FD_CLOSE | FD_READ)) == FD_CLOSE) { | |
265 Close(); | |
266 // Close might have deleted this object. We should return immediately. | |
267 return; | |
268 } | |
269 // The object was reset by WSAEnumNetworkEvents. Watch for the next signal. | |
270 watcher_.StartWatching(object, this); | |
271 | |
272 if (ev.lNetworkEvents == 0) { | |
273 // Occasionally the event is set even though there is no new data. | |
274 // The net seems to think that this is ignorable. | |
275 return; | |
276 } | |
277 if (ev.lNetworkEvents & FD_ACCEPT) { | |
278 Accept(); | |
279 } | |
280 if (ev.lNetworkEvents & FD_READ) { | |
281 if (reads_paused_) { | |
282 has_pending_reads_ = true; | |
283 } else { | |
284 Read(); | |
285 // Read might have deleted this object. We should return immediately. | |
286 } | |
287 } | |
288 } | |
289 #elif defined(OS_POSIX) | |
290 void StreamListenSocket::OnFileCanReadWithoutBlocking(int fd) { | |
291 switch (wait_state_) { | |
292 case WAITING_ACCEPT: | |
293 Accept(); | |
294 break; | |
295 case WAITING_READ: | |
296 if (reads_paused_) { | |
297 has_pending_reads_ = true; | |
298 } else { | |
299 Read(); | |
300 } | |
301 break; | |
302 default: | |
303 // Close() is called by Read() in the Linux case. | |
304 NOTREACHED(); | |
305 break; | |
306 } | |
307 } | |
308 | |
309 void StreamListenSocket::OnFileCanWriteWithoutBlocking(int fd) { | |
310 // MessagePumpLibevent callback, we don't listen for write events | |
311 // so we shouldn't ever reach here. | |
312 NOTREACHED(); | |
313 } | |
314 | |
315 #endif | |
316 | |
317 void StreamListenSocket::PauseReads() { | |
318 DCHECK(!reads_paused_); | |
319 reads_paused_ = true; | |
320 } | |
321 | |
322 void StreamListenSocket::ResumeReads() { | |
323 DCHECK(reads_paused_); | |
324 reads_paused_ = false; | |
325 if (has_pending_reads_) { | |
326 has_pending_reads_ = false; | |
327 Read(); | |
328 } | |
329 } | |
330 | |
331 } // namespace net | |
OLD | NEW |