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

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

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

Powered by Google App Engine
This is Rietveld 408576698