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