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

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

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

Powered by Google App Engine
This is Rietveld 408576698