103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found in the LICENSE file. 403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "device/serial/data_sink_receiver.h" 603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <limits> 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/bind.h" 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "device/serial/async_waiter.h" 1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace device { 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Represents a flush of data that has not been completed. 1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class DataSinkReceiver::PendingFlush { 1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public: 1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) PendingFlush(); 1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Initializes this PendingFlush with |num_bytes|, the number of bytes to 2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // flush. 2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void SetNumBytesToFlush(uint32_t num_bytes); 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Attempts to discard |bytes_to_flush_| bytes from |handle|. Returns 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // MOJO_RESULT_OK on success, MOJO_RESULT_SHOULD_WAIT if fewer than 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // |bytes_to_flush_| bytes were flushed or the error if one is encountered 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // discarding data from |handle|. 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MojoResult Flush(mojo::DataPipeConsumerHandle handle); 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Whether this PendingFlush has received the number of bytes to flush. 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool received_flush() { return received_flush_; } 3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) private: 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Whether this PendingFlush has received the number of bytes to flush. 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool received_flush_; 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The remaining number of bytes to flush. 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32_t bytes_to_flush_; 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}; 3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// A ReadOnlyBuffer implementation that provides a view of a data pipe owned by 4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// a DataSinkReceiver. 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class DataSinkReceiver::Buffer : public ReadOnlyBuffer { 4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public: 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Buffer(scoped_refptr<DataSinkReceiver> receiver, 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const char* buffer, 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32_t buffer_size); 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual ~Buffer(); 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void Cancel(int32_t error); 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // ReadOnlyBuffer overrides. 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual const char* GetData() OVERRIDE; 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual uint32_t GetSize() OVERRIDE; 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void Done(uint32_t bytes_read) OVERRIDE; 5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void DoneWithError(uint32_t bytes_read, int32_t error) OVERRIDE; 5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) private: 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The DataSinkReceiver whose data pipe we are providing a view. 5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<DataSinkReceiver> receiver_; 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const char* buffer_; 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32_t buffer_size_; 6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Whether this receive has been cancelled. 6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool cancelled_; 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If |cancelled_|, contains the cancellation error to report. 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int32_t cancellation_error_; 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}; 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)DataSinkReceiver::DataSinkReceiver(const ReadyCallback& ready_callback, 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const CancelCallback& cancel_callback, 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const ErrorCallback& error_callback) 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : ready_callback_(ready_callback), 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cancel_callback_(cancel_callback), 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) error_callback_(error_callback), 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_in_use_(NULL), 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shut_down_(false), 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) weak_factory_(this) { 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::ShutDown() { 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) shut_down_ = true; 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (waiter_) 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) waiter_.reset(); 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)DataSinkReceiver::~DataSinkReceiver() { 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::Init(mojo::ScopedDataPipeConsumerHandle handle) { 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (handle_.is_valid()) { 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchFatalError(); 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) handle_ = handle.Pass(); 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) StartWaiting(); 9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::Cancel(int32_t error) { 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If we have sent a ReportBytesSentAndError but have not received the 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // response, that ReportBytesSentAndError message will appear to the 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // DataSinkClient to be caused by this Cancel message. In that case, we ignore 10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the cancel. 10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!pending_flushes_.empty() && !pending_flushes_.back()->received_flush()) 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If there is a buffer is in use, mark the buffer as cancelled and notify the 11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // client by calling |cancel_callback_|. The sink implementation may or may 11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // not take the cancellation into account when deciding what error (if any) to 11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // return. If the sink returns an error, we ignore the cancellation error. 11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Otherwise, if the sink does not report an error, we override that with the 11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // cancellation error. Once a cancellation has been received, the next report 11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // sent to the client will always contain an error; the error returned by the 11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // sink or the cancellation error if the sink does not return an error. 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (buffer_in_use_) { 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_in_use_->Cancel(error); 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!cancel_callback_.is_null()) 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cancel_callback_.Run(error); 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If there is no buffer in use, immediately report the error and cancel the 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // waiting for the data pipe if one exists. This transitions straight into the 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // state after the sink has returned an error. 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) waiter_.reset(); 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ReportBytesSentAndError(0, error); 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::OnConnectionError() { 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchFatalError(); 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::StartWaiting() { 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(!waiter_ && !shut_down_); 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) waiter_.reset( 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new AsyncWaiter(handle_.get(), 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MOJO_HANDLE_SIGNAL_READABLE, 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&DataSinkReceiver::OnDoneWaiting, this))); 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::OnDoneWaiting(MojoResult result) { 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(waiter_ && !shut_down_); 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) waiter_.reset(); 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (result != MOJO_RESULT_OK) { 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchFatalError(); 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If there are any queued flushes (from ReportBytesSentAndError()), let them 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // flush data from the data pipe. 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!pending_flushes_.empty()) { 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MojoResult result = pending_flushes_.front()->Flush(handle_.get()); 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (result == MOJO_RESULT_OK) { 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pending_flushes_.pop(); 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else if (result != MOJO_RESULT_SHOULD_WAIT) { 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchFatalError(); 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) StartWaiting(); 16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const void* data = NULL; 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32_t num_bytes = std::numeric_limits<uint32_t>::max(); 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) result = mojo::BeginReadDataRaw( 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) handle_.get(), &data, &num_bytes, MOJO_READ_DATA_FLAG_NONE); 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (result != MOJO_RESULT_OK) { 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchFatalError(); 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_in_use_ = new Buffer(this, static_cast<const char*>(data), num_bytes); 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ready_callback_.Run(scoped_ptr<ReadOnlyBuffer>(buffer_in_use_)); 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::Done(uint32_t bytes_read) { 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!DoneInternal(bytes_read)) 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client()->ReportBytesSent(bytes_read); 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) StartWaiting(); 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::DoneWithError(uint32_t bytes_read, int32_t error) { 18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!DoneInternal(bytes_read)) 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ReportBytesSentAndError(bytes_read, error); 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool DataSinkReceiver::DoneInternal(uint32_t bytes_read) { 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (shut_down_) 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(buffer_in_use_); 19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_in_use_ = NULL; 19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MojoResult result = mojo::EndReadDataRaw(handle_.get(), bytes_read); 19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (result != MOJO_RESULT_OK) { 19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DispatchFatalError(); 19603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::ReportBytesSentAndError(uint32_t bytes_read, 20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int32_t error) { 20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // When we encounter an error, we must discard the data from any sends already 20403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // in the data pipe before we can resume dispatching data to the sink. We add 20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // a pending flush here. The response containing the number of bytes to flush 20603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // is handled in SetNumBytesToFlush(). The actual flush is handled in 20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // OnDoneWaiting(). 20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pending_flushes_.push(linked_ptr<PendingFlush>(new PendingFlush())); 20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) client()->ReportBytesSentAndError( 21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bytes_read, 21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) error, 21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&DataSinkReceiver::SetNumBytesToFlush, 21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) weak_factory_.GetWeakPtr())); 21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::SetNumBytesToFlush(uint32_t bytes_to_flush) { 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(!pending_flushes_.empty()); 21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(!pending_flushes_.back()->received_flush()); 21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pending_flushes_.back()->SetNumBytesToFlush(bytes_to_flush); 22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!waiter_) 22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) StartWaiting(); 22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::DispatchFatalError() { 22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (shut_down_) 22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ShutDown(); 22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!error_callback_.is_null()) 23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) error_callback_.Run(); 23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)DataSinkReceiver::Buffer::Buffer(scoped_refptr<DataSinkReceiver> receiver, 23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const char* buffer, 23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32_t buffer_size) 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : receiver_(receiver), 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_(buffer), 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_size_(buffer_size), 23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cancelled_(false), 24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cancellation_error_(0) { 24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)DataSinkReceiver::Buffer::~Buffer() { 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!receiver_.get()) 24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (cancelled_) 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_->DoneWithError(0, cancellation_error_); 24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_->Done(0); 25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::Buffer::Cancel(int32_t error) { 25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cancelled_ = true; 25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cancellation_error_ = error; 25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char* DataSinkReceiver::Buffer::GetData() { 25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return buffer_; 25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)uint32_t DataSinkReceiver::Buffer::GetSize() { 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return buffer_size_; 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::Buffer::Done(uint32_t bytes_read) { 26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (cancelled_) 26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_->DoneWithError(bytes_read, cancellation_error_); 26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else 26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_->Done(bytes_read); 27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_ = NULL; 27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_ = NULL; 27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_size_ = 0; 27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::Buffer::DoneWithError(uint32_t bytes_read, 27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int32_t error) { 27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_->DoneWithError(bytes_read, error); 27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) receiver_ = NULL; 27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_ = NULL; 28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_size_ = 0; 28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)DataSinkReceiver::PendingFlush::PendingFlush() 28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : received_flush_(false), bytes_to_flush_(0) { 28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 28703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataSinkReceiver::PendingFlush::SetNumBytesToFlush(uint32_t num_bytes) { 28803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(!received_flush_); 28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) received_flush_ = true; 29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bytes_to_flush_ = num_bytes; 29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)MojoResult DataSinkReceiver::PendingFlush::Flush( 29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) mojo::DataPipeConsumerHandle handle) { 29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(received_flush_); 29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32_t num_bytes = bytes_to_flush_; 29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MojoResult result = 29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) mojo::ReadDataRaw(handle, NULL, &num_bytes, MOJO_READ_DATA_FLAG_DISCARD); 29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (result != MOJO_RESULT_OK) 30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return result; 30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(num_bytes <= bytes_to_flush_); 30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bytes_to_flush_ -= num_bytes; 30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return bytes_to_flush_ == 0 ? MOJO_RESULT_OK : MOJO_RESULT_SHOULD_WAIT; 30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 30603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace device 307