| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "upload_element_reader.h" |
| |
| #include <utility> |
| |
| #include "src/lib/fxl/logging.h" |
| |
| namespace http { |
| |
| UploadElementReader::UploadElementReader() : err_(ZX_OK) {} |
| UploadElementReader::~UploadElementReader() = default; |
| |
| SocketUploadElementReader::SocketUploadElementReader(zx::socket socket) |
| : socket_(std::move(socket)) {} |
| |
| SocketUploadElementReader::~SocketUploadElementReader() {} |
| |
| size_t SocketUploadElementReader::size() { return kUnknownSize; } |
| |
| bool SocketUploadElementReader::ReadAvailable(std::ostream* os) { |
| while (true) { |
| size_t num_bytes = buf_.size(); |
| err_ = socket_.read(0u, buf_.data(), num_bytes, &num_bytes); |
| if (err_ == ZX_ERR_SHOULD_WAIT) { |
| err_ = socket_.wait_one(ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, |
| zx::time::infinite(), nullptr); |
| if (err_ == ZX_OK) |
| continue; // retry now that the socket is ready |
| } |
| |
| if (err_ != ZX_OK) { |
| // If the other end closes the socket, we get MX_ERR_PEER_CLOSED. |
| if (err_ == ZX_ERR_PEER_CLOSED) { |
| err_ = ZX_OK; |
| return false; |
| } |
| FXL_VLOG(1) << "SocketUploadElementReader: result=" << err_; |
| return false; |
| } |
| |
| os->write(buf_.data(), num_bytes); |
| if (!*os) { |
| // TODO(toshik): better result code? |
| err_ = ZX_ERR_BUFFER_TOO_SMALL; |
| FXL_VLOG(1) << "SocketUploadElementReader: result=" << err_; |
| return false; |
| } else { |
| return true; |
| } |
| } |
| } |
| |
| VmoUploadElementReader::VmoUploadElementReader(zx::vmo vmo) |
| : vmo_(std::move(vmo)), offset_(0) { |
| err_ = vmo_.get_size(&size_); |
| } |
| |
| VmoUploadElementReader::VmoUploadElementReader(zx::vmo vmo, uint64_t size) |
| : vmo_(std::move(vmo)), size_(size), offset_(0) {} |
| |
| VmoUploadElementReader::~VmoUploadElementReader() {} |
| |
| size_t VmoUploadElementReader::size() { return size_; } |
| |
| bool VmoUploadElementReader::ReadAvailable(std::ostream* os) { |
| const size_t remaining_bytes = size_ - offset_; |
| const size_t bytes_to_process = std::min(remaining_bytes, buf_.size()); |
| |
| err_ = vmo_.read(buf_.data(), offset_, bytes_to_process); |
| if (err_ != ZX_OK) { |
| FXL_VLOG(1) << "VmoUploadElementReader: result=" << err_; |
| return false; |
| } |
| |
| if (bytes_to_process > 0) { |
| os->write(buf_.data(), bytes_to_process); |
| if (!*os) { |
| FXL_VLOG(1) << "VmoUploadElementReader: Unable to write to stream."; |
| // TODO(toshik): better result code? |
| err_ = ZX_ERR_BUFFER_TOO_SMALL; |
| return false; |
| } |
| offset_ += bytes_to_process; |
| |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| } // namespace http |