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();