Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / socket / socket_libevent.cc
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 SocketDescriptor SocketLibevent::ReleaseConnectedSocket() {
110   StopWatchingAndCleanUp();
111   SocketDescriptor socket_fd = socket_fd_;
112   socket_fd_ = kInvalidSocket;
113   return socket_fd;
114 }
115
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
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
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
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
192 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
209 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
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
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
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
295 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
304 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
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
328 bool SocketLibevent::HasPeerAddress() const {
329   DCHECK(thread_checker_.CalledOnValidThread());
330   return peer_address_ != NULL;
331 }
332
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
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
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
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
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
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
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
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
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
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
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
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