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.
5 #include "net/socket/socket_libevent.h"
8 #include <netinet/in.h>
9 #include <sys/socket.h>
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"
23 int MapAcceptError(int 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".
31 return ERR_IO_PENDING
;
33 return MapSystemError(os_error
);
37 int MapConnectError(int os_error
) {
40 return ERR_IO_PENDING
;
42 return ERR_NETWORK_ACCESS_DENIED
;
44 return ERR_CONNECTION_TIMED_OUT
;
46 int net_error
= MapSystemError(os_error
);
47 if (net_error
== ERR_FAILED
)
48 return ERR_CONNECTION_FAILED
; // More specific than ERR_FAILED.
56 SocketLibevent::SocketLibevent()
57 : socket_fd_(kInvalidSocket
),
60 waiting_connect_(false) {
63 SocketLibevent::~SocketLibevent() {
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
);
74 socket_fd_
= CreatePlatformSocket(
77 address_family
== AF_UNIX
? 0 : IPPROTO_TCP
);
79 PLOG(ERROR
) << "CreatePlatformSocket() returned an error, errno=" << errno
;
80 return MapSystemError(errno
);
83 if (SetNonBlocking(socket_fd_
)) {
84 int rv
= MapSystemError(errno
);
92 int SocketLibevent::AdoptConnectedSocket(SocketDescriptor socket
,
93 const SockaddrStorage
& address
) {
94 DCHECK(thread_checker_
.CalledOnValidThread());
95 DCHECK_EQ(kInvalidSocket
, socket_fd_
);
99 if (SetNonBlocking(socket_fd_
)) {
100 int rv
= MapSystemError(errno
);
105 SetPeerAddress(address
);
109 SocketDescriptor
SocketLibevent::ReleaseConnectedSocket() {
110 StopWatchingAndCleanUp();
111 SocketDescriptor socket_fd
= socket_fd_
;
112 socket_fd_
= kInvalidSocket
;
116 int SocketLibevent::Bind(const SockaddrStorage
& address
) {
117 DCHECK(thread_checker_
.CalledOnValidThread());
118 DCHECK_NE(kInvalidSocket
, socket_fd_
);
120 int rv
= bind(socket_fd_
, address
.addr
, address
.addr_len
);
122 PLOG(ERROR
) << "bind() returned an error, errno=" << errno
;
123 return MapSystemError(errno
);
129 int SocketLibevent::Listen(int backlog
) {
130 DCHECK(thread_checker_
.CalledOnValidThread());
131 DCHECK_NE(kInvalidSocket
, socket_fd_
);
132 DCHECK_LT(0, backlog
);
134 int rv
= listen(socket_fd_
, backlog
);
136 PLOG(ERROR
) << "listen() returned an error, errno=" << errno
;
137 return MapSystemError(errno
);
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());
149 DCHECK(!callback
.is_null());
151 int rv
= DoAccept(socket
);
152 if (rv
!= ERR_IO_PENDING
)
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
);
162 accept_socket_
= socket
;
163 accept_callback_
= callback
;
164 return ERR_IO_PENDING
;
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());
174 SetPeerAddress(address
);
176 int rv
= DoConnect();
177 if (rv
!= ERR_IO_PENDING
)
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
);
187 write_callback_
= callback
;
188 waiting_connect_
= true;
189 return ERR_IO_PENDING
;
192 bool SocketLibevent::IsConnected() const {
193 DCHECK(thread_checker_
.CalledOnValidThread());
195 if (socket_fd_
== kInvalidSocket
|| waiting_connect_
)
198 // Checks if connection is alive.
200 int rv
= HANDLE_EINTR(recv(socket_fd_
, &c
, 1, MSG_PEEK
));
203 if (rv
== -1 && errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
)
209 bool SocketLibevent::IsConnectedAndIdle() const {
210 DCHECK(thread_checker_
.CalledOnValidThread());
212 if (socket_fd_
== kInvalidSocket
|| waiting_connect_
)
215 // Check if connection is alive and we haven't received any data
218 int rv
= HANDLE_EINTR(recv(socket_fd_
, &c
, 1, MSG_PEEK
));
221 if (errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
)
227 int SocketLibevent::Read(IOBuffer
* buf
,
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
);
238 int rv
= DoRead(buf
, buf_len
);
239 if (rv
!= ERR_IO_PENDING
)
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
);
250 read_buf_len_
= buf_len
;
251 read_callback_
= callback
;
252 return ERR_IO_PENDING
;
255 int SocketLibevent::Write(IOBuffer
* buf
,
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
);
266 int rv
= DoWrite(buf
, buf_len
);
267 if (rv
== ERR_IO_PENDING
)
268 rv
= WaitForWrite(buf
, buf_len
, callback
);
272 int SocketLibevent::WaitForWrite(IOBuffer
* buf
,
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
);
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
);
290 write_buf_len_
= buf_len
;
291 write_callback_
= callback
;
292 return ERR_IO_PENDING
;
295 int SocketLibevent::GetLocalAddress(SockaddrStorage
* address
) const {
296 DCHECK(thread_checker_
.CalledOnValidThread());
299 if (getsockname(socket_fd_
, address
->addr
, &address
->addr_len
) < 0)
300 return MapSystemError(errno
);
304 int SocketLibevent::GetPeerAddress(SockaddrStorage
* address
) const {
305 DCHECK(thread_checker_
.CalledOnValidThread());
308 if (!HasPeerAddress())
309 return ERR_SOCKET_NOT_CONNECTED
;
311 *address
= *peer_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()
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
324 DCHECK(!peer_address_
);
325 peer_address_
.reset(new SockaddrStorage(address
));
328 bool SocketLibevent::HasPeerAddress() const {
329 DCHECK(thread_checker_
.CalledOnValidThread());
330 return peer_address_
!= NULL
;
333 void SocketLibevent::Close() {
334 DCHECK(thread_checker_
.CalledOnValidThread());
336 StopWatchingAndCleanUp();
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
;
345 void SocketLibevent::OnFileCanReadWithoutBlocking(int fd
) {
346 DCHECK(!accept_callback_
.is_null() || !read_callback_
.is_null());
347 if (!accept_callback_
.is_null()) {
349 } else { // !read_callback_.is_null()
354 void SocketLibevent::OnFileCanWriteWithoutBlocking(int fd
) {
355 DCHECK(!write_callback_
.is_null());
356 if (waiting_connect_
) {
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
));
369 return MapAcceptError(errno
);
371 scoped_ptr
<SocketLibevent
> accepted_socket(new SocketLibevent
);
372 int rv
= accepted_socket
->AdoptConnectedSocket(new_socket
, new_peer_address
);
376 *socket
= accepted_socket
.Pass();
380 void SocketLibevent::AcceptCompleted() {
381 DCHECK(accept_socket_
);
382 int rv
= DoAccept(accept_socket_
);
383 if (rv
== ERR_IO_PENDING
)
386 bool ok
= accept_socket_watcher_
.StopWatchingFileDescriptor();
388 accept_socket_
= NULL
;
389 base::ResetAndReturn(&accept_callback_
).Run(rv
);
392 int SocketLibevent::DoConnect() {
393 int rv
= HANDLE_EINTR(connect(socket_fd_
,
395 peer_address_
->addr_len
));
397 return rv
== 0 ? OK
: MapConnectError(errno
);
400 void SocketLibevent::ConnectCompleted() {
401 // Get the error that connect() completed with.
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.
409 int rv
= MapConnectError(errno
);
410 if (rv
== ERR_IO_PENDING
)
413 bool ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
415 waiting_connect_
= false;
416 base::ResetAndReturn(&write_callback_
).Run(rv
);
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
);
424 void SocketLibevent::ReadCompleted() {
425 int rv
= DoRead(read_buf_
.get(), read_buf_len_
);
426 if (rv
== ERR_IO_PENDING
)
429 bool ok
= read_socket_watcher_
.StopWatchingFileDescriptor();
433 base::ResetAndReturn(&read_callback_
).Run(rv
);
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
);
441 void SocketLibevent::WriteCompleted() {
442 int rv
= DoWrite(write_buf_
.get(), write_buf_len_
);
443 if (rv
== ERR_IO_PENDING
)
446 bool ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
450 base::ResetAndReturn(&write_callback_
).Run(rv
);
453 void SocketLibevent::StopWatchingAndCleanUp() {
454 bool ok
= accept_socket_watcher_
.StopWatchingFileDescriptor();
456 ok
= read_socket_watcher_
.StopWatchingFileDescriptor();
458 ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
461 if (!accept_callback_
.is_null()) {
462 accept_socket_
= NULL
;
463 accept_callback_
.Reset();
466 if (!read_callback_
.is_null()) {
469 read_callback_
.Reset();
472 if (!write_callback_
.is_null()) {
475 write_callback_
.Reset();
478 waiting_connect_
= false;
479 peer_address_
.reset();