1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file. 4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chromeos/dbus/pipe_reader.h" 6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/bind.h" 8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/posix/eintr_wrapper.h" 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/task_runner.h" 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/file_stream.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/io_buffer.h" 12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/net_errors.h" 13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace chromeos { 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuPipeReader::PipeReader(const scoped_refptr<base::TaskRunner>& task_runner, 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const IOCompleteCallback& callback) 18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : io_buffer_(new net::IOBufferWithSize(4096)), 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu task_runner_(task_runner), 20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch callback_(callback), 21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch weak_ptr_factory_(this) {} 22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochPipeReader::~PipeReader() { 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)base::File PipeReader::StartIO() { 27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Use a pipe to collect data 28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int pipe_fds[2]; 29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const int status = HANDLE_EINTR(pipe(pipe_fds)); 30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (status < 0) { 31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PLOG(ERROR) << "pipe"; 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return base::File(); 33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::File pipe_write_end(pipe_fds[1]); 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Pass ownership of pipe_fds[0] to data_stream_, which will close it. 36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch data_stream_.reset(new net::FileStream( 37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::File(pipe_fds[0]), task_runner_)); 38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Post an initial async read to setup data collection 40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int rv = data_stream_->Read( 41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch io_buffer_.get(), io_buffer_->size(), 42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr())); 43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (rv != net::ERR_IO_PENDING) { 44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "Unable to post initial read"; 45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return base::File(); 46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return pipe_write_end.Pass(); 48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid PipeReader::OnDataReady(int byte_count) { 51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DVLOG(1) << "OnDataReady byte_count " << byte_count; 52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (byte_count <= 0) { 53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch callback_.Run(); // signal creator to take data and delete us 54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch AcceptData(io_buffer_->data(), byte_count); 58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Post another read 60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int rv = data_stream_->Read( 61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch io_buffer_.get(), io_buffer_->size(), 62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr())); 63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (rv != net::ERR_IO_PENDING) { 64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "Unable to post another read"; 65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // TODO(sleffler) do something more intelligent? 66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochPipeReaderForString::PipeReaderForString( 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const scoped_refptr<base::TaskRunner>& task_runner, 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const IOCompleteCallback& callback) 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : PipeReader(task_runner, callback) { 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid PipeReaderForString::AcceptData(const char *data, int byte_count) { 76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch data_.append(data, byte_count); 77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid PipeReaderForString::GetData(std::string* data) { 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch data_.swap(*data); 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} // namespace chromeos 84