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_posix.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 SocketPosix::SocketPosix()
57 : socket_fd_(kInvalidSocket
),
60 waiting_connect_(false) {}
62 SocketPosix::~SocketPosix() {
66 int SocketPosix::Open(int address_family
) {
67 DCHECK(thread_checker_
.CalledOnValidThread());
68 DCHECK_EQ(kInvalidSocket
, socket_fd_
);
69 DCHECK(address_family
== AF_INET
||
70 address_family
== AF_INET6
||
71 address_family
== AF_UNIX
);
73 socket_fd_
= CreatePlatformSocket(
76 address_family
== AF_UNIX
? 0 : IPPROTO_TCP
);
78 PLOG(ERROR
) << "CreatePlatformSocket() returned an error, errno=" << errno
;
79 return MapSystemError(errno
);
82 if (SetNonBlocking(socket_fd_
)) {
83 int rv
= MapSystemError(errno
);
91 int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket
,
92 const SockaddrStorage
& address
) {
93 DCHECK(thread_checker_
.CalledOnValidThread());
94 DCHECK_EQ(kInvalidSocket
, socket_fd_
);
98 if (SetNonBlocking(socket_fd_
)) {
99 int rv
= MapSystemError(errno
);
104 SetPeerAddress(address
);
108 SocketDescriptor
SocketPosix::ReleaseConnectedSocket() {
109 StopWatchingAndCleanUp();
110 SocketDescriptor socket_fd
= socket_fd_
;
111 socket_fd_
= kInvalidSocket
;
115 int SocketPosix::Bind(const SockaddrStorage
& address
) {
116 DCHECK(thread_checker_
.CalledOnValidThread());
117 DCHECK_NE(kInvalidSocket
, socket_fd_
);
119 int rv
= bind(socket_fd_
, address
.addr
, address
.addr_len
);
121 PLOG(ERROR
) << "bind() returned an error, errno=" << errno
;
122 return MapSystemError(errno
);
128 int SocketPosix::Listen(int backlog
) {
129 DCHECK(thread_checker_
.CalledOnValidThread());
130 DCHECK_NE(kInvalidSocket
, socket_fd_
);
131 DCHECK_LT(0, backlog
);
133 int rv
= listen(socket_fd_
, backlog
);
135 PLOG(ERROR
) << "listen() returned an error, errno=" << errno
;
136 return MapSystemError(errno
);
142 int SocketPosix::Accept(scoped_ptr
<SocketPosix
>* socket
,
143 const CompletionCallback
& callback
) {
144 DCHECK(thread_checker_
.CalledOnValidThread());
145 DCHECK_NE(kInvalidSocket
, socket_fd_
);
146 DCHECK(accept_callback_
.is_null());
148 DCHECK(!callback
.is_null());
150 int rv
= DoAccept(socket
);
151 if (rv
!= ERR_IO_PENDING
)
154 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
155 socket_fd_
, true, base::MessageLoopForIO::WATCH_READ
,
156 &accept_socket_watcher_
, this)) {
157 PLOG(ERROR
) << "WatchFileDescriptor failed on accept, errno " << errno
;
158 return MapSystemError(errno
);
161 accept_socket_
= socket
;
162 accept_callback_
= callback
;
163 return ERR_IO_PENDING
;
166 int SocketPosix::Connect(const SockaddrStorage
& address
,
167 const CompletionCallback
& callback
) {
168 DCHECK(thread_checker_
.CalledOnValidThread());
169 DCHECK_NE(kInvalidSocket
, socket_fd_
);
170 DCHECK(!waiting_connect_
);
171 DCHECK(!callback
.is_null());
173 SetPeerAddress(address
);
175 int rv
= DoConnect();
176 if (rv
!= ERR_IO_PENDING
)
179 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
180 socket_fd_
, true, base::MessageLoopForIO::WATCH_WRITE
,
181 &write_socket_watcher_
, this)) {
182 PLOG(ERROR
) << "WatchFileDescriptor failed on connect, errno " << errno
;
183 return MapSystemError(errno
);
186 write_callback_
= callback
;
187 waiting_connect_
= true;
188 return ERR_IO_PENDING
;
191 bool SocketPosix::IsConnected() const {
192 DCHECK(thread_checker_
.CalledOnValidThread());
194 if (socket_fd_
== kInvalidSocket
|| waiting_connect_
)
197 // Checks if connection is alive.
199 int rv
= HANDLE_EINTR(recv(socket_fd_
, &c
, 1, MSG_PEEK
));
202 if (rv
== -1 && errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
)
208 bool SocketPosix::IsConnectedAndIdle() const {
209 DCHECK(thread_checker_
.CalledOnValidThread());
211 if (socket_fd_
== kInvalidSocket
|| waiting_connect_
)
214 // Check if connection is alive and we haven't received any data
217 int rv
= HANDLE_EINTR(recv(socket_fd_
, &c
, 1, MSG_PEEK
));
220 if (errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
)
226 int SocketPosix::Read(IOBuffer
* buf
,
228 const CompletionCallback
& callback
) {
229 DCHECK(thread_checker_
.CalledOnValidThread());
230 DCHECK_NE(kInvalidSocket
, socket_fd_
);
231 DCHECK(!waiting_connect_
);
232 CHECK(read_callback_
.is_null());
233 // Synchronous operation not supported
234 DCHECK(!callback
.is_null());
235 DCHECK_LT(0, buf_len
);
237 int rv
= DoRead(buf
, buf_len
);
238 if (rv
!= ERR_IO_PENDING
)
241 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
242 socket_fd_
, true, base::MessageLoopForIO::WATCH_READ
,
243 &read_socket_watcher_
, this)) {
244 PLOG(ERROR
) << "WatchFileDescriptor failed on read, errno " << errno
;
245 return MapSystemError(errno
);
249 read_buf_len_
= buf_len
;
250 read_callback_
= callback
;
251 return ERR_IO_PENDING
;
254 int SocketPosix::Write(IOBuffer
* buf
,
256 const CompletionCallback
& callback
) {
257 DCHECK(thread_checker_
.CalledOnValidThread());
258 DCHECK_NE(kInvalidSocket
, socket_fd_
);
259 DCHECK(!waiting_connect_
);
260 CHECK(write_callback_
.is_null());
261 // Synchronous operation not supported
262 DCHECK(!callback
.is_null());
263 DCHECK_LT(0, buf_len
);
265 int rv
= DoWrite(buf
, buf_len
);
266 if (rv
== ERR_IO_PENDING
)
267 rv
= WaitForWrite(buf
, buf_len
, callback
);
271 int SocketPosix::WaitForWrite(IOBuffer
* buf
,
273 const CompletionCallback
& callback
) {
274 DCHECK(thread_checker_
.CalledOnValidThread());
275 DCHECK_NE(kInvalidSocket
, socket_fd_
);
276 DCHECK(write_callback_
.is_null());
277 // Synchronous operation not supported
278 DCHECK(!callback
.is_null());
279 DCHECK_LT(0, buf_len
);
281 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
282 socket_fd_
, true, base::MessageLoopForIO::WATCH_WRITE
,
283 &write_socket_watcher_
, this)) {
284 PLOG(ERROR
) << "WatchFileDescriptor failed on write, errno " << errno
;
285 return MapSystemError(errno
);
289 write_buf_len_
= buf_len
;
290 write_callback_
= callback
;
291 return ERR_IO_PENDING
;
294 int SocketPosix::GetLocalAddress(SockaddrStorage
* address
) const {
295 DCHECK(thread_checker_
.CalledOnValidThread());
298 if (getsockname(socket_fd_
, address
->addr
, &address
->addr_len
) < 0)
299 return MapSystemError(errno
);
303 int SocketPosix::GetPeerAddress(SockaddrStorage
* address
) const {
304 DCHECK(thread_checker_
.CalledOnValidThread());
307 if (!HasPeerAddress())
308 return ERR_SOCKET_NOT_CONNECTED
;
310 *address
= *peer_address_
;
314 void SocketPosix::SetPeerAddress(const SockaddrStorage
& address
) {
315 DCHECK(thread_checker_
.CalledOnValidThread());
316 // |peer_address_| will be non-NULL if Connect() has been called. Unless
317 // Close() is called to reset the internal state, a second call to Connect()
319 // Please note that we don't allow a second Connect() even if the previous
320 // Connect() has failed. Connecting the same |socket_| again after a
321 // connection attempt failed results in unspecified behavior according to
323 DCHECK(!peer_address_
);
324 peer_address_
.reset(new SockaddrStorage(address
));
327 bool SocketPosix::HasPeerAddress() const {
328 DCHECK(thread_checker_
.CalledOnValidThread());
329 return peer_address_
!= NULL
;
332 void SocketPosix::Close() {
333 DCHECK(thread_checker_
.CalledOnValidThread());
335 StopWatchingAndCleanUp();
337 if (socket_fd_
!= kInvalidSocket
) {
338 if (IGNORE_EINTR(close(socket_fd_
)) < 0)
339 PLOG(ERROR
) << "close() returned an error, errno=" << errno
;
340 socket_fd_
= kInvalidSocket
;
344 void SocketPosix::OnFileCanReadWithoutBlocking(int fd
) {
345 DCHECK(!accept_callback_
.is_null() || !read_callback_
.is_null());
346 if (!accept_callback_
.is_null()) {
348 } else { // !read_callback_.is_null()
353 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd
) {
354 DCHECK(!write_callback_
.is_null());
355 if (waiting_connect_
) {
362 int SocketPosix::DoAccept(scoped_ptr
<SocketPosix
>* socket
) {
363 SockaddrStorage new_peer_address
;
364 int new_socket
= HANDLE_EINTR(accept(socket_fd_
,
365 new_peer_address
.addr
,
366 &new_peer_address
.addr_len
));
368 return MapAcceptError(errno
);
370 scoped_ptr
<SocketPosix
> accepted_socket(new SocketPosix
);
371 int rv
= accepted_socket
->AdoptConnectedSocket(new_socket
, new_peer_address
);
375 *socket
= accepted_socket
.Pass();
379 void SocketPosix::AcceptCompleted() {
380 DCHECK(accept_socket_
);
381 int rv
= DoAccept(accept_socket_
);
382 if (rv
== ERR_IO_PENDING
)
385 bool ok
= accept_socket_watcher_
.StopWatchingFileDescriptor();
387 accept_socket_
= NULL
;
388 base::ResetAndReturn(&accept_callback_
).Run(rv
);
391 int SocketPosix::DoConnect() {
392 int rv
= HANDLE_EINTR(connect(socket_fd_
,
394 peer_address_
->addr_len
));
396 return rv
== 0 ? OK
: MapConnectError(errno
);
399 void SocketPosix::ConnectCompleted() {
400 // Get the error that connect() completed with.
402 socklen_t len
= sizeof(os_error
);
403 if (getsockopt(socket_fd_
, SOL_SOCKET
, SO_ERROR
, &os_error
, &len
) == 0) {
404 // TCPSocketPosix expects errno to be set.
408 int rv
= MapConnectError(errno
);
409 if (rv
== ERR_IO_PENDING
)
412 bool ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
414 waiting_connect_
= false;
415 base::ResetAndReturn(&write_callback_
).Run(rv
);
418 int SocketPosix::DoRead(IOBuffer
* buf
, int buf_len
) {
419 int rv
= HANDLE_EINTR(read(socket_fd_
, buf
->data(), buf_len
));
420 return rv
>= 0 ? rv
: MapSystemError(errno
);
423 void SocketPosix::ReadCompleted() {
424 int rv
= DoRead(read_buf_
.get(), read_buf_len_
);
425 if (rv
== ERR_IO_PENDING
)
428 bool ok
= read_socket_watcher_
.StopWatchingFileDescriptor();
432 base::ResetAndReturn(&read_callback_
).Run(rv
);
435 int SocketPosix::DoWrite(IOBuffer
* buf
, int buf_len
) {
436 int rv
= HANDLE_EINTR(write(socket_fd_
, buf
->data(), buf_len
));
437 return rv
>= 0 ? rv
: MapSystemError(errno
);
440 void SocketPosix::WriteCompleted() {
441 int rv
= DoWrite(write_buf_
.get(), write_buf_len_
);
442 if (rv
== ERR_IO_PENDING
)
445 bool ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
449 base::ResetAndReturn(&write_callback_
).Run(rv
);
452 void SocketPosix::StopWatchingAndCleanUp() {
453 bool ok
= accept_socket_watcher_
.StopWatchingFileDescriptor();
455 ok
= read_socket_watcher_
.StopWatchingFileDescriptor();
457 ok
= write_socket_watcher_
.StopWatchingFileDescriptor();
460 if (!accept_callback_
.is_null()) {
461 accept_socket_
= NULL
;
462 accept_callback_
.Reset();
465 if (!read_callback_
.is_null()) {
468 read_callback_
.Reset();
471 if (!write_callback_
.is_null()) {
474 write_callback_
.Reset();
477 waiting_connect_
= false;
478 peer_address_
.reset();