Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: net/base/default_listen_socket.cc

Issue 10161005: Add DefaultListenSocket. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix year in license header Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698