blob: 77fc6eee0893bb846adb39582e0057f8aeea1d05 [file] [log] [blame]
// Copyright 2019 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 "payload-streamer.h"
#include <lib/async/default.h>
#include <lib/fidl-async/cpp/bind.h>
namespace disk_pave {
PayloadStreamer::PayloadStreamer(zx::channel chan, fbl::unique_fd payload)
: payload_(std::move(payload)) {
fidl::Bind(async_get_default_dispatcher(), std::move(chan), this);
}
PayloadStreamer::~PayloadStreamer() {
if (!eof_reached_) {
// Reads the entire file if it wasn't completely read by the channel.
// This is necessary due to implementation of streaming protocol which
// forces entire file to be transferred.
char buf[8192];
while (read(payload_.get(), &buf, sizeof(buf)) > 0)
continue;
}
}
void PayloadStreamer::RegisterVmo(zx::vmo vmo, RegisterVmoCompleter::Sync completer) {
if (vmo_) {
completer.Reply(ZX_ERR_ALREADY_BOUND);
return;
}
auto status = mapper_.Map(vmo, 0, 0, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);
if (status != ZX_OK) {
completer.Reply(status);
return;
}
vmo_ = std::move(vmo);
completer.Reply(ZX_OK);
}
void PayloadStreamer::ReadData(ReadDataCompleter::Sync completer) {
::llcpp::fuchsia::paver::ReadResult result = {};
if (!vmo_) {
zx_status_t status = ZX_ERR_BAD_STATE;
result.set_err(fidl::unowned_ptr(&status));
completer.Reply(std::move(result));
return;
}
if (eof_reached_) {
result.set_eof(fidl::unowned_ptr(&eof_reached_));
completer.Reply(std::move(result));
return;
}
ssize_t n = read(payload_.get(), mapper_.start(), mapper_.size());
if (n == 0) {
eof_reached_ = true;
result.set_eof(fidl::unowned_ptr(&eof_reached_));
completer.Reply(std::move(result));
} else if (n < 0) {
zx_status_t status = ZX_ERR_IO;
result.set_err(fidl::unowned_ptr(&status));
completer.Reply(std::move(result));
} else {
// completer.Reply must be called from within this else block since otherwise
// |info| will go out of scope
::llcpp::fuchsia::paver::ReadInfo info{.offset = 0, .size = static_cast<uint64_t>(n)};
result.set_info(fidl::unowned_ptr(&info));
completer.Reply(std::move(result));
}
}
} // namespace disk_pave