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