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 int SocketLibevent::Bind(const SockaddrStorage
& address
) {
110 DCHECK(thread_checker_
.CalledOnValidThread());
111 DCHECK_NE(kInvalidSocket
, socket_fd_
);
113 int rv
= bind(socket_fd_
, address
.addr
, address
.addr_len
);
115 PLOG(ERROR
) << "bind() returned an error, errno=" << errno
;
116 return MapSystemError(errno
);
122 int SocketLibevent::Listen(int backlog
) {
123 DCHECK(thread_checker_
.CalledOnValidThread());
124 DCHECK_NE(kInvalidSocket
, socket_fd_
);
125 DCHECK_LT(0, backlog
);
127 int rv
= listen(socket_fd_
, backlog
);
129 PLOG(ERROR
) << "listen() returned an error, errno=" << errno
;
130 return MapSystemError(errno
);
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());
142 DCHECK(!callback
.is_null());
144 int rv
= DoAccept(socket
);
145 if (rv
!= ERR_IO_PENDING
)
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
);
155 accept_socket_
= socket
;
156 accept_callback_
= callback
;
157 return ERR_IO_PENDING
;
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());
167 SetPeerAddress(address
);
169 int rv
= DoConnect();
170 if (rv
!= ERR_IO_PENDING
)
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
);
180 write_callback_
= callback
;
181 waiting_connect_
= true;
182 return ERR_IO_PENDING
;
185 bool SocketLibevent::IsConnected() const {
186 DCHECK(thread_checker_
.CalledOnValidThread());
188 if (socket_fd_
== kInvalidSocket
|| waiting_connect_
)
191 // Checks if connection is alive.
193 int rv
= HANDLE_EINTR(recv(socket_fd_
, &c
, 1, MSG_PEEK
));
196 if (rv
== -1 && errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
)
202 bool SocketLibevent::IsConnectedAndIdle() const {
203 DCHECK(thread_checker_
.CalledOnValidThread());
205 if (socket_fd_
== kInvalidSocket
|| waiting_connect_
)
208 // Check if connection is alive and we haven't received any data
211 int rv
= HANDLE_EINTR(recv(socket_fd_
, &c
, 1, MSG_PEEK
));
214 if (errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
)
220 int SocketLibevent::Read(IOBuffer
* buf
,
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
);
231 int rv
= DoRead(buf
, buf_len
);
232 if (rv
!= ERR_IO_PENDING
)
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
);
243 read_buf_len_
= buf_len
;
244 read_callback_
= callback
;
245 return ERR_IO_PENDING
;
248 int SocketLibevent::Write(IOBuffer
* buf
,
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
);
259 int rv
= DoWrite(buf
, buf_len
);
260 if (rv
== ERR_IO_PENDING
)
261 rv
= WaitForWrite(buf
, buf_len
, callback
);
265 int SocketLibevent::WaitForWrite(IOBuffer
* buf
,
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
);
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
);
283 write_buf_len_
= buf_len
;
284 write_callback_
= callback
;
285 return ERR_IO_PENDING
;
288 int SocketLibevent::GetLocalAddress(SockaddrStorage
* address
) const {
289 DCHECK(thread_checker_
.CalledOnValidThread());
292 if (getsockname(socket_fd_
, address
->addr
, &address
->addr_len
) < 0)
293 return MapSystemError(errno
);
297 int SocketLibevent::GetPeerAddress(SockaddrStorage
* address
) const {
298 DCHECK(thread_checker_
.CalledOnValidThread());
301 if (!HasPeerAddress())
302 return ERR_SOCKET_NOT_CONNECTED
;
304 *address
= *peer_address_
;
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()
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
317 DCHECK(!peer_address_
);
318 peer_address_
.reset(new SockaddrStorage(address
));
321 bool SocketLibevent::HasPeerAddress() const {
322 DCHECK(thread_checker_
.CalledOnValidThread());
323 return peer_address_
!= NULL
;
326 void SocketLibevent::Close() {
327 DCHECK(thread_checker_
.CalledOnValidThread());
329 bool ok
= accept_socket_watcher_
.StopWatchingFileDescriptor();
331 ok
= read_socket_watcher_
.StopWatchingFileDescriptor();
333 ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
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
;
342 if (!accept_callback_
.is_null()) {
343 accept_socket_
= NULL
;
344 accept_callback_
.Reset();
347 if (!read_callback_
.is_null()) {
350 read_callback_
.Reset();
353 if (!write_callback_
.is_null()) {
356 write_callback_
.Reset();
359 waiting_connect_
= false;
360 peer_address_
.reset();
363 void SocketLibevent::OnFileCanReadWithoutBlocking(int fd
) {
364 DCHECK(!accept_callback_
.is_null() || !read_callback_
.is_null());
365 if (!accept_callback_
.is_null()) {
367 } else { // !read_callback_.is_null()
372 void SocketLibevent::OnFileCanWriteWithoutBlocking(int fd
) {
373 DCHECK(!write_callback_
.is_null());
374 if (waiting_connect_
) {
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
));
387 return MapAcceptError(errno
);
389 scoped_ptr
<SocketLibevent
> accepted_socket(new SocketLibevent
);
390 int rv
= accepted_socket
->AdoptConnectedSocket(new_socket
, new_peer_address
);
394 *socket
= accepted_socket
.Pass();
398 void SocketLibevent::AcceptCompleted() {
399 DCHECK(accept_socket_
);
400 int rv
= DoAccept(accept_socket_
);
401 if (rv
== ERR_IO_PENDING
)
404 bool ok
= accept_socket_watcher_
.StopWatchingFileDescriptor();
406 accept_socket_
= NULL
;
407 base::ResetAndReturn(&accept_callback_
).Run(rv
);
410 int SocketLibevent::DoConnect() {
411 int rv
= HANDLE_EINTR(connect(socket_fd_
,
413 peer_address_
->addr_len
));
415 return rv
== 0 ? OK
: MapConnectError(errno
);
418 void SocketLibevent::ConnectCompleted() {
419 // Get the error that connect() completed with.
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.
427 int rv
= MapConnectError(errno
);
428 if (rv
== ERR_IO_PENDING
)
431 bool ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
433 waiting_connect_
= false;
434 base::ResetAndReturn(&write_callback_
).Run(rv
);
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
);
442 void SocketLibevent::ReadCompleted() {
443 int rv
= DoRead(read_buf_
.get(), read_buf_len_
);
444 if (rv
== ERR_IO_PENDING
)
447 bool ok
= read_socket_watcher_
.StopWatchingFileDescriptor();
451 base::ResetAndReturn(&read_callback_
).Run(rv
);
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
);
459 void SocketLibevent::WriteCompleted() {
460 int rv
= DoWrite(write_buf_
.get(), write_buf_len_
);
461 if (rv
== ERR_IO_PENDING
)
464 bool ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
468 base::ResetAndReturn(&write_callback_
).Run(rv
);