11e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko// Copyright 2015 The Chromium OS Authors. All rights reserved.
21e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
31e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko// found in the LICENSE file.
41e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/streams/stream_utils.h>
61e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
71e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko#include <limits>
81e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko#include <base/bind.h>
109ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/message_loops/message_loop.h>
119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/streams/stream_errors.h>
121e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
139ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
141e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkonamespace stream_utils {
151e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkonamespace {
1749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
1849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// Status of asynchronous CopyData operation.
1949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkostruct CopyDataState {
209ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko  brillo::StreamPtr in_stream;
219ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko  brillo::StreamPtr out_stream;
2249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  std::vector<uint8_t> buffer;
2349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  uint64_t remaining_to_copy;
2449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  uint64_t size_copied;
2549fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  CopyDataSuccessCallback success_callback;
2649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  CopyDataErrorCallback error_callback;
2749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko};
2849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
2949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// Async CopyData I/O error callback.
3049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkovoid OnCopyDataError(const std::shared_ptr<CopyDataState>& state,
319ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko                     const brillo::Error* error) {
3249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->error_callback.Run(std::move(state->in_stream),
3349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko                            std::move(state->out_stream), error);
3449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko}
3549fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
3649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// Forward declaration.
3749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkovoid PerformRead(const std::shared_ptr<CopyDataState>& state);
3849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
3949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// Callback from read operation for CopyData. Writes the read data to the output
4049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// stream and invokes PerformRead when done to restart the copy cycle.
4149fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkovoid PerformWrite(const std::shared_ptr<CopyDataState>& state, size_t size) {
4249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  if (size == 0) {
4349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko    state->success_callback.Run(std::move(state->in_stream),
4449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko                                std::move(state->out_stream),
4549fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko                                state->size_copied);
4649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko    return;
4749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  }
4849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->size_copied += size;
4949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  CHECK_GE(state->remaining_to_copy, size);
5049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->remaining_to_copy -= size;
5149fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
529ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko  brillo::ErrorPtr error;
5349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  bool success = state->out_stream->WriteAllAsync(
5449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko      state->buffer.data(), size, base::Bind(&PerformRead, state),
5549fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko      base::Bind(&OnCopyDataError, state), &error);
5649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
5749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  if (!success)
5849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko    OnCopyDataError(state, error.get());
5949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko}
6049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
6149fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// Performs the read part of asynchronous CopyData operation. Reads the data
6249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// from input stream and invokes PerformWrite when done to write the data to
6349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko// the output stream.
6449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkovoid PerformRead(const std::shared_ptr<CopyDataState>& state) {
659ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko  brillo::ErrorPtr error;
6649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  const uint64_t buffer_size = state->buffer.size();
6749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  // |buffer_size| is guaranteed to fit in size_t, so |size_to_read| value will
6849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  // also not overflow size_t, so the static_cast below is safe.
6949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  size_t size_to_read =
7049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko      static_cast<size_t>(std::min(buffer_size, state->remaining_to_copy));
7149fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  if (size_to_read == 0)
7249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko    return PerformWrite(state, 0);  // Nothing more to read. Finish operation.
7349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  bool success = state->in_stream->ReadAsync(
7449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko      state->buffer.data(), size_to_read, base::Bind(PerformWrite, state),
7549fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko      base::Bind(OnCopyDataError, state), &error);
7649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
7749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  if (!success)
7849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko    OnCopyDataError(state, error.get());
7949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko}
8049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
8149fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko}  // anonymous namespace
8249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
831e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool ErrorStreamClosed(const tracked_objects::Location& location,
841e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                       ErrorPtr* error) {
851e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  Error::AddTo(error,
861e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               location,
871e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kDomain,
881e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kStreamClosed,
891e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               "Stream is closed");
901e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  return false;
911e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko}
921e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
931e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool ErrorOperationNotSupported(const tracked_objects::Location& location,
941e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                                ErrorPtr* error) {
951e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  Error::AddTo(error,
961e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               location,
971e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kDomain,
981e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kOperationNotSupported,
991e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               "Stream operation not supported");
1001e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  return false;
1011e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko}
1021e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1031e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool ErrorReadPastEndOfStream(const tracked_objects::Location& location,
1041e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                              ErrorPtr* error) {
1051e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  Error::AddTo(error,
1061e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               location,
1071e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kDomain,
1081e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kPartialData,
1091e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               "Reading past the end of stream");
1101e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  return false;
1111e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko}
1121e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1131b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenkobool ErrorOperationTimeout(const tracked_objects::Location& location,
1141b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko                           ErrorPtr* error) {
1151b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko  Error::AddTo(error,
1161b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko               location,
1171b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko               errors::stream::kDomain,
1181b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko               errors::stream::kTimeout,
1191b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko               "Operation timed out");
1201b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko  return false;
1211b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko}
1221b79239785bf964fd5f1a607a6ed9c9bbb57a4b1Alex Vakulenko
1231e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool CheckInt64Overflow(const tracked_objects::Location& location,
1241e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                        uint64_t position,
1251e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                        int64_t offset,
1261e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                        ErrorPtr* error) {
1271e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  if (offset < 0) {
1281e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    // Subtracting the offset. Make sure we do not underflow.
1291e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    uint64_t unsigned_offset = static_cast<uint64_t>(-offset);
1301e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    if (position >= unsigned_offset)
1311e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      return true;
1321e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  } else {
1331e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    // Adding the offset. Make sure we do not overflow unsigned 64 bits first.
1341e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    if (position <= std::numeric_limits<uint64_t>::max() - offset) {
1351e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      // We definitely will not overflow the unsigned 64 bit integer.
1361e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      // Now check that we end up within the limits of signed 64 bit integer.
1371e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      uint64_t new_position = position + offset;
1381e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      uint64_t max = std::numeric_limits<int64_t>::max();
1391e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      if (new_position <= max)
1401e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko        return true;
1411e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    }
1421e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  }
1431e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  Error::AddTo(error,
1441e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               location,
1451e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kDomain,
1461e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               errors::stream::kInvalidParameter,
1471e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko               "The stream offset value is out of range");
1481e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  return false;
1491e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko}
1501e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1511e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenkobool CalculateStreamPosition(const tracked_objects::Location& location,
1521e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                             int64_t offset,
1531e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                             Stream::Whence whence,
1541e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                             uint64_t current_position,
1551e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                             uint64_t stream_size,
1561e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                             uint64_t* new_position,
1571e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                             ErrorPtr* error) {
1581e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  uint64_t pos = 0;
1591e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  switch (whence) {
1601e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    case Stream::Whence::FROM_BEGIN:
1611e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      pos = 0;
1621e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      break;
1631e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1641e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    case Stream::Whence::FROM_CURRENT:
1651e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      pos = current_position;
1661e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      break;
1671e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1681e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    case Stream::Whence::FROM_END:
1691e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      pos = stream_size;
1701e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      break;
1711e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1721e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    default:
1731e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      Error::AddTo(error,
1741e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                   location,
1751e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                   errors::stream::kDomain,
1761e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                   errors::stream::kInvalidParameter,
1771e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko                   "Invalid stream position whence");
1781e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko      return false;
1791e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  }
1801e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1811e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  if (!CheckInt64Overflow(location, pos, offset, error))
1821e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko    return false;
1831e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
1841e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  *new_position = static_cast<uint64_t>(pos + offset);
1851e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko  return true;
1861e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko}
1871e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko
18849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkovoid CopyData(StreamPtr in_stream,
18949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              StreamPtr out_stream,
19049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              const CopyDataSuccessCallback& success_callback,
19149fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              const CopyDataErrorCallback& error_callback) {
19249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  CopyData(std::move(in_stream), std::move(out_stream),
19349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko           std::numeric_limits<uint64_t>::max(), 4096, success_callback,
19449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko           error_callback);
19549fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko}
19649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
19749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenkovoid CopyData(StreamPtr in_stream,
19849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              StreamPtr out_stream,
19949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              uint64_t max_size_to_copy,
20049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              size_t buffer_size,
20149fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              const CopyDataSuccessCallback& success_callback,
20249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko              const CopyDataErrorCallback& error_callback) {
20349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  auto state = std::make_shared<CopyDataState>();
20449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->in_stream = std::move(in_stream);
20549fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->out_stream = std::move(out_stream);
20649fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->buffer.resize(buffer_size);
20749fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->remaining_to_copy = max_size_to_copy;
20849fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->size_copied = 0;
20949fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->success_callback = success_callback;
21049fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko  state->error_callback = error_callback;
2119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko  brillo::MessageLoop::current()->PostTask(FROM_HERE,
21249fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko                                             base::Bind(&PerformRead, state));
21349fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko}
21449fb1ce7956110497bd7cad33b3a954faca4b77cAlex Vakulenko
2151e582b39cf77c6ec0ed908153b40e3875a30a2e5Alex Vakulenko}  // namespace stream_utils
2169ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko}  // namespace brillo
217