• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MapAcceptError(int os_error)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 
MapConnectError(int os_error)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 
SocketLibevent()56 SocketLibevent::SocketLibevent()
57     : socket_fd_(kInvalidSocket),
58       read_buf_len_(0),
59       write_buf_len_(0),
60       waiting_connect_(false) {
61 }
62 
~SocketLibevent()63 SocketLibevent::~SocketLibevent() {
64   Close();
65 }
66 
Open(int address_family)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 
AdoptConnectedSocket(SocketDescriptor socket,const SockaddrStorage & address)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 
ReleaseConnectedSocket()109 SocketDescriptor SocketLibevent::ReleaseConnectedSocket() {
110   StopWatchingAndCleanUp();
111   SocketDescriptor socket_fd = socket_fd_;
112   socket_fd_ = kInvalidSocket;
113   return socket_fd;
114 }
115 
Bind(const SockaddrStorage & address)116 int SocketLibevent::Bind(const SockaddrStorage& address) {
117   DCHECK(thread_checker_.CalledOnValidThread());
118   DCHECK_NE(kInvalidSocket, socket_fd_);
119 
120   int rv = bind(socket_fd_, address.addr, address.addr_len);
121   if (rv < 0) {
122     PLOG(ERROR) << "bind() returned an error, errno=" << errno;
123     return MapSystemError(errno);
124   }
125 
126   return OK;
127 }
128 
Listen(int backlog)129 int SocketLibevent::Listen(int backlog) {
130   DCHECK(thread_checker_.CalledOnValidThread());
131   DCHECK_NE(kInvalidSocket, socket_fd_);
132   DCHECK_LT(0, backlog);
133 
134   int rv = listen(socket_fd_, backlog);
135   if (rv < 0) {
136     PLOG(ERROR) << "listen() returned an error, errno=" << errno;
137     return MapSystemError(errno);
138   }
139 
140   return OK;
141 }
142 
Accept(scoped_ptr<SocketLibevent> * socket,const CompletionCallback & callback)143 int SocketLibevent::Accept(scoped_ptr<SocketLibevent>* socket,
144                            const CompletionCallback& callback) {
145   DCHECK(thread_checker_.CalledOnValidThread());
146   DCHECK_NE(kInvalidSocket, socket_fd_);
147   DCHECK(accept_callback_.is_null());
148   DCHECK(socket);
149   DCHECK(!callback.is_null());
150 
151   int rv = DoAccept(socket);
152   if (rv != ERR_IO_PENDING)
153     return rv;
154 
155   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
156           socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
157           &accept_socket_watcher_, this)) {
158     PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
159     return MapSystemError(errno);
160   }
161 
162   accept_socket_ = socket;
163   accept_callback_ = callback;
164   return ERR_IO_PENDING;
165 }
166 
Connect(const SockaddrStorage & address,const CompletionCallback & callback)167 int SocketLibevent::Connect(const SockaddrStorage& address,
168                             const CompletionCallback& callback) {
169   DCHECK(thread_checker_.CalledOnValidThread());
170   DCHECK_NE(kInvalidSocket, socket_fd_);
171   DCHECK(!waiting_connect_);
172   DCHECK(!callback.is_null());
173 
174   SetPeerAddress(address);
175 
176   int rv = DoConnect();
177   if (rv != ERR_IO_PENDING)
178     return rv;
179 
180   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
181           socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
182           &write_socket_watcher_, this)) {
183     PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
184     return MapSystemError(errno);
185   }
186 
187   write_callback_ = callback;
188   waiting_connect_ = true;
189   return ERR_IO_PENDING;
190 }
191 
IsConnected() const192 bool SocketLibevent::IsConnected() const {
193   DCHECK(thread_checker_.CalledOnValidThread());
194 
195   if (socket_fd_ == kInvalidSocket || waiting_connect_)
196     return false;
197 
198   // Checks if connection is alive.
199   char c;
200   int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
201   if (rv == 0)
202     return false;
203   if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
204     return false;
205 
206   return true;
207 }
208 
IsConnectedAndIdle() const209 bool SocketLibevent::IsConnectedAndIdle() const {
210   DCHECK(thread_checker_.CalledOnValidThread());
211 
212   if (socket_fd_ == kInvalidSocket || waiting_connect_)
213     return false;
214 
215   // Check if connection is alive and we haven't received any data
216   // unexpectedly.
217   char c;
218   int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
219   if (rv >= 0)
220     return false;
221   if (errno != EAGAIN && errno != EWOULDBLOCK)
222     return false;
223 
224   return true;
225 }
226 
Read(IOBuffer * buf,int buf_len,const CompletionCallback & callback)227 int SocketLibevent::Read(IOBuffer* buf,
228                          int buf_len,
229                          const CompletionCallback& callback) {
230   DCHECK(thread_checker_.CalledOnValidThread());
231   DCHECK_NE(kInvalidSocket, socket_fd_);
232   DCHECK(!waiting_connect_);
233   DCHECK(read_callback_.is_null());
234   // Synchronous operation not supported
235   DCHECK(!callback.is_null());
236   DCHECK_LT(0, buf_len);
237 
238   int rv = DoRead(buf, buf_len);
239   if (rv != ERR_IO_PENDING)
240     return rv;
241 
242   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
243           socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
244           &read_socket_watcher_, this)) {
245     PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
246     return MapSystemError(errno);
247   }
248 
249   read_buf_ = buf;
250   read_buf_len_ = buf_len;
251   read_callback_ = callback;
252   return ERR_IO_PENDING;
253 }
254 
Write(IOBuffer * buf,int buf_len,const CompletionCallback & callback)255 int SocketLibevent::Write(IOBuffer* buf,
256                           int buf_len,
257                           const CompletionCallback& callback) {
258   DCHECK(thread_checker_.CalledOnValidThread());
259   DCHECK_NE(kInvalidSocket, socket_fd_);
260   DCHECK(!waiting_connect_);
261   DCHECK(write_callback_.is_null());
262   // Synchronous operation not supported
263   DCHECK(!callback.is_null());
264   DCHECK_LT(0, buf_len);
265 
266   int rv = DoWrite(buf, buf_len);
267   if (rv == ERR_IO_PENDING)
268     rv = WaitForWrite(buf, buf_len, callback);
269   return rv;
270 }
271 
WaitForWrite(IOBuffer * buf,int buf_len,const CompletionCallback & callback)272 int SocketLibevent::WaitForWrite(IOBuffer* buf,
273                                  int buf_len,
274                                  const CompletionCallback& callback) {
275   DCHECK(thread_checker_.CalledOnValidThread());
276   DCHECK_NE(kInvalidSocket, socket_fd_);
277   DCHECK(write_callback_.is_null());
278   // Synchronous operation not supported
279   DCHECK(!callback.is_null());
280   DCHECK_LT(0, buf_len);
281 
282   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
283           socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
284           &write_socket_watcher_, this)) {
285     PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
286     return MapSystemError(errno);
287   }
288 
289   write_buf_ = buf;
290   write_buf_len_ = buf_len;
291   write_callback_ = callback;
292   return ERR_IO_PENDING;
293 }
294 
GetLocalAddress(SockaddrStorage * address) const295 int SocketLibevent::GetLocalAddress(SockaddrStorage* address) const {
296   DCHECK(thread_checker_.CalledOnValidThread());
297   DCHECK(address);
298 
299   if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
300     return MapSystemError(errno);
301   return OK;
302 }
303 
GetPeerAddress(SockaddrStorage * address) const304 int SocketLibevent::GetPeerAddress(SockaddrStorage* address) const {
305   DCHECK(thread_checker_.CalledOnValidThread());
306   DCHECK(address);
307 
308   if (!HasPeerAddress())
309     return ERR_SOCKET_NOT_CONNECTED;
310 
311   *address = *peer_address_;
312   return OK;
313 }
314 
SetPeerAddress(const SockaddrStorage & address)315 void SocketLibevent::SetPeerAddress(const SockaddrStorage& address) {
316   DCHECK(thread_checker_.CalledOnValidThread());
317   // |peer_address_| will be non-NULL if Connect() has been called. Unless
318   // Close() is called to reset the internal state, a second call to Connect()
319   // is not allowed.
320   // Please note that we don't allow a second Connect() even if the previous
321   // Connect() has failed. Connecting the same |socket_| again after a
322   // connection attempt failed results in unspecified behavior according to
323   // POSIX.
324   DCHECK(!peer_address_);
325   peer_address_.reset(new SockaddrStorage(address));
326 }
327 
HasPeerAddress() const328 bool SocketLibevent::HasPeerAddress() const {
329   DCHECK(thread_checker_.CalledOnValidThread());
330   return peer_address_ != NULL;
331 }
332 
Close()333 void SocketLibevent::Close() {
334   DCHECK(thread_checker_.CalledOnValidThread());
335 
336   StopWatchingAndCleanUp();
337 
338   if (socket_fd_ != kInvalidSocket) {
339     if (IGNORE_EINTR(close(socket_fd_)) < 0)
340       PLOG(ERROR) << "close() returned an error, errno=" << errno;
341     socket_fd_ = kInvalidSocket;
342   }
343 }
344 
OnFileCanReadWithoutBlocking(int fd)345 void SocketLibevent::OnFileCanReadWithoutBlocking(int fd) {
346   DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
347   if (!accept_callback_.is_null()) {
348     AcceptCompleted();
349   } else {  // !read_callback_.is_null()
350     ReadCompleted();
351   }
352 }
353 
OnFileCanWriteWithoutBlocking(int fd)354 void SocketLibevent::OnFileCanWriteWithoutBlocking(int fd) {
355   DCHECK(!write_callback_.is_null());
356   if (waiting_connect_) {
357     ConnectCompleted();
358   } else {
359     WriteCompleted();
360   }
361 }
362 
DoAccept(scoped_ptr<SocketLibevent> * socket)363 int SocketLibevent::DoAccept(scoped_ptr<SocketLibevent>* socket) {
364   SockaddrStorage new_peer_address;
365   int new_socket = HANDLE_EINTR(accept(socket_fd_,
366                                        new_peer_address.addr,
367                                        &new_peer_address.addr_len));
368   if (new_socket < 0)
369     return MapAcceptError(errno);
370 
371   scoped_ptr<SocketLibevent> accepted_socket(new SocketLibevent);
372   int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
373   if (rv != OK)
374     return rv;
375 
376   *socket = accepted_socket.Pass();
377   return OK;
378 }
379 
AcceptCompleted()380 void SocketLibevent::AcceptCompleted() {
381   DCHECK(accept_socket_);
382   int rv = DoAccept(accept_socket_);
383   if (rv == ERR_IO_PENDING)
384     return;
385 
386   bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
387   DCHECK(ok);
388   accept_socket_ = NULL;
389   base::ResetAndReturn(&accept_callback_).Run(rv);
390 }
391 
DoConnect()392 int SocketLibevent::DoConnect() {
393   int rv = HANDLE_EINTR(connect(socket_fd_,
394                                 peer_address_->addr,
395                                 peer_address_->addr_len));
396   DCHECK_GE(0, rv);
397   return rv == 0 ? OK : MapConnectError(errno);
398 }
399 
ConnectCompleted()400 void SocketLibevent::ConnectCompleted() {
401   // Get the error that connect() completed with.
402   int os_error = 0;
403   socklen_t len = sizeof(os_error);
404   if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
405     // TCPSocketLibevent expects errno to be set.
406     errno = os_error;
407   }
408 
409   int rv = MapConnectError(errno);
410   if (rv == ERR_IO_PENDING)
411     return;
412 
413   bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
414   DCHECK(ok);
415   waiting_connect_ = false;
416   base::ResetAndReturn(&write_callback_).Run(rv);
417 }
418 
DoRead(IOBuffer * buf,int buf_len)419 int SocketLibevent::DoRead(IOBuffer* buf, int buf_len) {
420   int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
421   return rv >= 0 ? rv : MapSystemError(errno);
422 }
423 
ReadCompleted()424 void SocketLibevent::ReadCompleted() {
425   int rv = DoRead(read_buf_.get(), read_buf_len_);
426   if (rv == ERR_IO_PENDING)
427     return;
428 
429   bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
430   DCHECK(ok);
431   read_buf_ = NULL;
432   read_buf_len_ = 0;
433   base::ResetAndReturn(&read_callback_).Run(rv);
434 }
435 
DoWrite(IOBuffer * buf,int buf_len)436 int SocketLibevent::DoWrite(IOBuffer* buf, int buf_len) {
437   int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
438   return rv >= 0 ? rv : MapSystemError(errno);
439 }
440 
WriteCompleted()441 void SocketLibevent::WriteCompleted() {
442   int rv = DoWrite(write_buf_.get(), write_buf_len_);
443   if (rv == ERR_IO_PENDING)
444     return;
445 
446   bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
447   DCHECK(ok);
448   write_buf_ = NULL;
449   write_buf_len_ = 0;
450   base::ResetAndReturn(&write_callback_).Run(rv);
451 }
452 
StopWatchingAndCleanUp()453 void SocketLibevent::StopWatchingAndCleanUp() {
454   bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
455   DCHECK(ok);
456   ok = read_socket_watcher_.StopWatchingFileDescriptor();
457   DCHECK(ok);
458   ok = write_socket_watcher_.StopWatchingFileDescriptor();
459   DCHECK(ok);
460 
461   if (!accept_callback_.is_null()) {
462     accept_socket_ = NULL;
463     accept_callback_.Reset();
464   }
465 
466   if (!read_callback_.is_null()) {
467     read_buf_ = NULL;
468     read_buf_len_ = 0;
469     read_callback_.Reset();
470   }
471 
472   if (!write_callback_.is_null()) {
473     write_buf_ = NULL;
474     write_buf_len_ = 0;
475     write_callback_.Reset();
476   }
477 
478   waiting_connect_ = false;
479   peer_address_.reset();
480 }
481 
482 }  // namespace net
483