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

Side by Side Diff: net/socket/socket_libevent.cc

Issue 348803003: Refactor tcp socket and unix domain socket. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Revert the behavior change of calling RecordFastOpenStatus() Created 6 years, 5 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/socket/socket_libevent.h"
6
7 #include <errno.h>
8 #include <netinet/in.h>
9 #include <sys/socket.h>
10
11 #include "base/callback_helpers.h"
12 #include "base/logging.h"
13 #include "base/posix/eintr_wrapper.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/ip_endpoint.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_util.h"
18
19 namespace net {
20
21 namespace {
22
23 int MapAcceptError(int os_error) {
24 switch (os_error) {
25 // If the client aborts the connection before the server calls accept,
26 // POSIX specifies accept should fail with ECONNABORTED. The server can
27 // ignore the error and just call accept again, so we map the error to
28 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
29 // 5.11, "Connection Abort before accept Returns".
30 case ECONNABORTED:
31 return ERR_IO_PENDING;
32 default:
33 return MapSystemError(os_error);
34 }
35 }
36
37 int MapConnectError(int os_error) {
38 switch (os_error) {
39 case EINPROGRESS:
40 return ERR_IO_PENDING;
41 case EACCES:
42 return ERR_NETWORK_ACCESS_DENIED;
43 case ETIMEDOUT:
44 return ERR_CONNECTION_TIMED_OUT;
45 default: {
46 int net_error = MapSystemError(os_error);
47 if (net_error == ERR_FAILED)
48 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
49 return net_error;
50 }
51 }
52 }
53
54 } // namespace
55
56 SocketLibevent::SocketLibevent()
57 : socket_fd_(kInvalidSocket),
58 read_buf_len_(0),
59 write_buf_len_(0),
60 waiting_connect_(false) {
61 }
62
63 SocketLibevent::~SocketLibevent() {
64 Close();
65 }
66
67 int SocketLibevent::Open(int address_family) {
68 DCHECK(thread_checker_.CalledOnValidThread());
69 DCHECK_EQ(kInvalidSocket, socket_fd_);
70 DCHECK(address_family == AF_INET ||
71 address_family == AF_INET6 ||
72 address_family == AF_UNIX);
73
74 socket_fd_ = CreatePlatformSocket(
75 address_family,
76 SOCK_STREAM,
77 address_family == AF_UNIX ? 0 : IPPROTO_TCP);
78 if (socket_fd_ < 0) {
79 PLOG(ERROR) << "CreatePlatformSocket() returned an error, errno=" << errno;
80 return MapSystemError(errno);
81 }
82
83 if (SetNonBlocking(socket_fd_)) {
84 int rv = MapSystemError(errno);
85 Close();
86 return rv;
87 }
88
89 return OK;
90 }
91
92 int SocketLibevent::AdoptConnectedSocket(SocketDescriptor socket,
93 const SockaddrStorage& address) {
94 DCHECK(thread_checker_.CalledOnValidThread());
95 DCHECK_EQ(kInvalidSocket, socket_fd_);
96
97 socket_fd_ = socket;
98
99 if (SetNonBlocking(socket_fd_)) {
100 int rv = MapSystemError(errno);
101 Close();
102 return rv;
103 }
104
105 SetPeerAddress(address);
106 return OK;
107 }
108
109 int SocketLibevent::Bind(const SockaddrStorage& address) {
110 DCHECK(thread_checker_.CalledOnValidThread());
111 DCHECK_NE(kInvalidSocket, socket_fd_);
112
113 int rv = bind(socket_fd_, address.addr, address.addr_len);
114 if (rv < 0) {
115 PLOG(ERROR) << "bind() returned an error, errno=" << errno;
116 return MapSystemError(errno);
117 }
118
119 return OK;
120 }
121
122 int SocketLibevent::Listen(int backlog) {
123 DCHECK(thread_checker_.CalledOnValidThread());
124 DCHECK_NE(kInvalidSocket, socket_fd_);
125 DCHECK_LT(0, backlog);
126
127 int rv = listen(socket_fd_, backlog);
128 if (rv < 0) {
129 PLOG(ERROR) << "listen() returned an error, errno=" << errno;
130 return MapSystemError(errno);
131 }
132
133 return OK;
134 }
135
136 int SocketLibevent::Accept(scoped_ptr<SocketLibevent>* socket,
137 const CompletionCallback& callback) {
138 DCHECK(thread_checker_.CalledOnValidThread());
139 DCHECK_NE(kInvalidSocket, socket_fd_);
140 DCHECK(accept_callback_.is_null());
141 DCHECK(socket);
142 DCHECK(!callback.is_null());
143
144 int rv = DoAccept(socket);
145 if (rv != ERR_IO_PENDING)
146 return rv;
147
148 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
149 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
150 &accept_socket_watcher_, this)) {
151 PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
152 return MapSystemError(errno);
153 }
154
155 accept_socket_ = socket;
156 accept_callback_ = callback;
157 return ERR_IO_PENDING;
158 }
159
160 int SocketLibevent::Connect(const SockaddrStorage& address,
161 const CompletionCallback& callback) {
162 DCHECK(thread_checker_.CalledOnValidThread());
163 DCHECK_NE(kInvalidSocket, socket_fd_);
164 DCHECK(!waiting_connect_);
165 DCHECK(!callback.is_null());
166
167 SetPeerAddress(address);
168
169 int rv = DoConnect();
170 if (rv != ERR_IO_PENDING)
171 return rv;
172
173 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
174 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
175 &write_socket_watcher_, this)) {
176 PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
177 return MapSystemError(errno);
178 }
179
180 write_callback_ = callback;
181 waiting_connect_ = true;
182 return ERR_IO_PENDING;
183 }
184
185 bool SocketLibevent::IsConnected() const {
186 DCHECK(thread_checker_.CalledOnValidThread());
187
188 if (socket_fd_ == kInvalidSocket || waiting_connect_)
189 return false;
190
191 // Checks if connection is alive.
192 char c;
193 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
194 if (rv == 0)
195 return false;
196 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
197 return false;
198
199 return true;
200 }
201
202 bool SocketLibevent::IsConnectedAndIdle() const {
203 DCHECK(thread_checker_.CalledOnValidThread());
204
205 if (socket_fd_ == kInvalidSocket || waiting_connect_)
206 return false;
207
208 // Check if connection is alive and we haven't received any data
209 // unexpectedly.
210 char c;
211 int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
212 if (rv >= 0)
213 return false;
214 if (errno != EAGAIN && errno != EWOULDBLOCK)
215 return false;
216
217 return true;
218 }
219
220 int SocketLibevent::Read(IOBuffer* buf,
221 int buf_len,
222 const CompletionCallback& callback) {
223 DCHECK(thread_checker_.CalledOnValidThread());
224 DCHECK_NE(kInvalidSocket, socket_fd_);
225 DCHECK(!waiting_connect_);
226 DCHECK(read_callback_.is_null());
227 // Synchronous operation not supported
228 DCHECK(!callback.is_null());
229 DCHECK_LT(0, buf_len);
230
231 int rv = DoRead(buf, buf_len);
232 if (rv != ERR_IO_PENDING)
233 return rv;
234
235 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
236 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
237 &read_socket_watcher_, this)) {
238 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
239 return MapSystemError(errno);
240 }
241
242 read_buf_ = buf;
243 read_buf_len_ = buf_len;
244 read_callback_ = callback;
245 return ERR_IO_PENDING;
246 }
247
248 int SocketLibevent::Write(IOBuffer* buf,
249 int buf_len,
250 const CompletionCallback& callback) {
251 DCHECK(thread_checker_.CalledOnValidThread());
252 DCHECK_NE(kInvalidSocket, socket_fd_);
253 DCHECK(!waiting_connect_);
254 DCHECK(write_callback_.is_null());
255 // Synchronous operation not supported
256 DCHECK(!callback.is_null());
257 DCHECK_LT(0, buf_len);
258
259 int rv = DoWrite(buf, buf_len);
260 if (rv == ERR_IO_PENDING)
261 rv = WaitForWrite(buf, buf_len, callback);
262 return rv;
263 }
264
265 int SocketLibevent::WaitForWrite(IOBuffer* buf,
266 int buf_len,
267 const CompletionCallback& callback) {
268 DCHECK(thread_checker_.CalledOnValidThread());
269 DCHECK_NE(kInvalidSocket, socket_fd_);
270 DCHECK(write_callback_.is_null());
271 // Synchronous operation not supported
272 DCHECK(!callback.is_null());
273 DCHECK_LT(0, buf_len);
274
275 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
276 socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
277 &write_socket_watcher_, this)) {
278 PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
279 return MapSystemError(errno);
280 }
281
282 write_buf_ = buf;
283 write_buf_len_ = buf_len;
284 write_callback_ = callback;
285 return ERR_IO_PENDING;
286 }
287
288 int SocketLibevent::GetLocalAddress(SockaddrStorage* address) const {
289 DCHECK(thread_checker_.CalledOnValidThread());
290 DCHECK(address);
291
292 if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
293 return MapSystemError(errno);
294 return OK;
295 }
296
297 int SocketLibevent::GetPeerAddress(SockaddrStorage* address) const {
298 DCHECK(thread_checker_.CalledOnValidThread());
299 DCHECK(address);
300
301 if (!HasPeerAddress())
302 return ERR_SOCKET_NOT_CONNECTED;
303
304 *address = *peer_address_;
305 return OK;
306 }
307
308 void SocketLibevent::SetPeerAddress(const SockaddrStorage& address) {
309 DCHECK(thread_checker_.CalledOnValidThread());
310 // |peer_address_| will be non-NULL if Connect() has been called. Unless
311 // Close() is called to reset the internal state, a second call to Connect()
312 // is not allowed.
313 // Please note that we don't allow a second Connect() even if the previous
314 // Connect() has failed. Connecting the same |socket_| again after a
315 // connection attempt failed results in unspecified behavior according to
316 // POSIX.
317 DCHECK(!peer_address_);
318 peer_address_.reset(new SockaddrStorage(address));
319 }
320
321 bool SocketLibevent::HasPeerAddress() const {
322 DCHECK(thread_checker_.CalledOnValidThread());
323 return peer_address_ != NULL;
324 }
325
326 void SocketLibevent::Close() {
327 DCHECK(thread_checker_.CalledOnValidThread());
328
329 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
330 DCHECK(ok);
331 ok = read_socket_watcher_.StopWatchingFileDescriptor();
332 DCHECK(ok);
333 ok = write_socket_watcher_.StopWatchingFileDescriptor();
334 DCHECK(ok);
335
336 if (socket_fd_ != kInvalidSocket) {
337 if (IGNORE_EINTR(close(socket_fd_)) < 0)
338 PLOG(ERROR) << "close() returned an error, errno=" << errno;
339 socket_fd_ = kInvalidSocket;
340 }
341
342 if (!accept_callback_.is_null()) {
343 accept_socket_ = NULL;
344 accept_callback_.Reset();
345 }
346
347 if (!read_callback_.is_null()) {
348 read_buf_ = NULL;
349 read_buf_len_ = 0;
350 read_callback_.Reset();
351 }
352
353 if (!write_callback_.is_null()) {
354 write_buf_ = NULL;
355 write_buf_len_ = 0;
356 write_callback_.Reset();
357 }
358
359 waiting_connect_ = false;
360 peer_address_.reset();
361 }
362
363 void SocketLibevent::OnFileCanReadWithoutBlocking(int fd) {
364 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
365 if (!accept_callback_.is_null()) {
366 AcceptCompleted();
367 } else { // !read_callback_.is_null()
368 ReadCompleted();
369 }
370 }
371
372 void SocketLibevent::OnFileCanWriteWithoutBlocking(int fd) {
373 DCHECK(!write_callback_.is_null());
374 if (waiting_connect_) {
375 ConnectCompleted();
376 } else {
377 WriteCompleted();
378 }
379 }
380
381 int SocketLibevent::DoAccept(scoped_ptr<SocketLibevent>* socket) {
382 SockaddrStorage new_peer_address;
383 int new_socket = HANDLE_EINTR(accept(socket_fd_,
384 new_peer_address.addr,
385 &new_peer_address.addr_len));
386 if (new_socket < 0)
387 return MapAcceptError(errno);
388
389 scoped_ptr<SocketLibevent> accepted_socket(new SocketLibevent);
390 int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
391 if (rv != OK)
392 return rv;
393
394 *socket = accepted_socket.Pass();
395 return OK;
396 }
397
398 void SocketLibevent::AcceptCompleted() {
399 DCHECK(accept_socket_);
400 int rv = DoAccept(accept_socket_);
401 if (rv == ERR_IO_PENDING)
402 return;
403
404 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
405 DCHECK(ok);
406 accept_socket_ = NULL;
407 base::ResetAndReturn(&accept_callback_).Run(rv);
408 }
409
410 int SocketLibevent::DoConnect() {
411 int rv = HANDLE_EINTR(connect(socket_fd_,
412 peer_address_->addr,
413 peer_address_->addr_len));
414 DCHECK_GE(0, rv);
415 return rv == 0 ? OK : MapConnectError(errno);
416 }
417
418 void SocketLibevent::ConnectCompleted() {
419 // Get the error that connect() completed with.
420 int os_error = 0;
421 socklen_t len = sizeof(os_error);
422 if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
423 // TCPSocketLibevent expects errno to be set.
424 errno = os_error;
425 }
426
427 int rv = MapConnectError(errno);
428 if (rv == ERR_IO_PENDING)
429 return;
430
431 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
432 DCHECK(ok);
433 waiting_connect_ = false;
434 base::ResetAndReturn(&write_callback_).Run(rv);
435 }
436
437 int SocketLibevent::DoRead(IOBuffer* buf, int buf_len) {
438 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
439 return rv >= 0 ? rv : MapSystemError(errno);
440 }
441
442 void SocketLibevent::ReadCompleted() {
443 int rv = DoRead(read_buf_, read_buf_len_);
444 if (rv == ERR_IO_PENDING)
445 return;
446
447 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
448 DCHECK(ok);
449 read_buf_ = NULL;
450 read_buf_len_ = 0;
451 base::ResetAndReturn(&read_callback_).Run(rv);
452 }
453
454 int SocketLibevent::DoWrite(IOBuffer* buf, int buf_len) {
455 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
456 return rv >= 0 ? rv : MapSystemError(errno);
457 }
458
459 void SocketLibevent::WriteCompleted() {
460 int rv = DoWrite(write_buf_, write_buf_len_);
461 if (rv == ERR_IO_PENDING)
462 return;
463
464 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
465 DCHECK(ok);
466 write_buf_ = NULL;
467 write_buf_len_ = 0;
468 base::ResetAndReturn(&write_callback_).Run(rv);
469 }
470
471 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698