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