Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / base / async_socket_io_handler_posix.cc
blob2fffb844ff8afec64523dd9c4425c13aaafeaf2c
1 // Copyright 2013 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 "base/async_socket_io_handler.h"
7 #include <fcntl.h>
9 #include "base/posix/eintr_wrapper.h"
11 namespace base {
13 AsyncSocketIoHandler::AsyncSocketIoHandler()
14 : socket_(base::SyncSocket::kInvalidHandle),
15 pending_buffer_(NULL),
16 pending_buffer_len_(0),
17 is_watching_(false) {
20 AsyncSocketIoHandler::~AsyncSocketIoHandler() {
21 DCHECK(CalledOnValidThread());
24 void AsyncSocketIoHandler::OnFileCanReadWithoutBlocking(int socket) {
25 DCHECK(CalledOnValidThread());
26 DCHECK_EQ(socket, socket_);
27 DCHECK(!read_complete_.is_null());
29 if (pending_buffer_) {
30 int bytes_read = HANDLE_EINTR(read(socket_, pending_buffer_,
31 pending_buffer_len_));
32 DCHECK_GE(bytes_read, 0);
33 pending_buffer_ = NULL;
34 pending_buffer_len_ = 0;
35 read_complete_.Run(bytes_read > 0 ? bytes_read : 0);
36 } else {
37 // We're getting notifications that we can read from the socket while
38 // we're not waiting for data. In order to not starve the message loop,
39 // let's stop watching the fd and restart the watch when Read() is called.
40 is_watching_ = false;
41 socket_watcher_.StopWatchingFileDescriptor();
45 bool AsyncSocketIoHandler::Read(char* buffer, int buffer_len) {
46 DCHECK(CalledOnValidThread());
47 DCHECK(!read_complete_.is_null());
48 DCHECK(!pending_buffer_);
50 EnsureWatchingSocket();
52 int bytes_read = HANDLE_EINTR(read(socket_, buffer, buffer_len));
53 if (bytes_read < 0) {
54 if (errno == EAGAIN) {
55 pending_buffer_ = buffer;
56 pending_buffer_len_ = buffer_len;
57 } else {
58 NOTREACHED() << "read(): " << errno;
59 return false;
61 } else {
62 read_complete_.Run(bytes_read);
64 return true;
67 bool AsyncSocketIoHandler::Initialize(base::SyncSocket::Handle socket,
68 const ReadCompleteCallback& callback) {
69 DCHECK_EQ(socket_, base::SyncSocket::kInvalidHandle);
71 DetachFromThread();
73 socket_ = socket;
74 read_complete_ = callback;
76 // SyncSocket is blocking by default, so let's convert it to non-blocking.
77 int value = fcntl(socket, F_GETFL);
78 if (!(value & O_NONBLOCK)) {
79 // Set the socket to be non-blocking so we can do async reads.
80 if (fcntl(socket, F_SETFL, O_NONBLOCK) == -1) {
81 NOTREACHED();
82 return false;
86 return true;
89 void AsyncSocketIoHandler::EnsureWatchingSocket() {
90 DCHECK(CalledOnValidThread());
91 if (!is_watching_ && socket_ != base::SyncSocket::kInvalidHandle) {
92 is_watching_ = base::MessageLoopForIO::current()->WatchFileDescriptor(
93 socket_, true, base::MessageLoopForIO::WATCH_READ,
94 &socket_watcher_, this);
98 } // namespace base.