blob: a255806137fbee60c137a4effd4ad6acb70b8910 [file] [log] [blame]
// Copyright 2021 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 "src/devices/lib/goldfish/pipe_io/pipe_auto_reader.h"
#include <fidl/fuchsia.hardware.goldfish/cpp/wire.h>
#include <lib/async/cpp/task.h>
#include <lib/ddk/debug.h>
namespace goldfish {
// TODO(liyl): Currently the contents of the message should be read all at once.
// This should support reading long messages with pipe wait.
zx_status_t PipeAutoReader::AsyncReadWithHeader() {
auto read_result = ReadWithHeader(false);
if (read_result.is_ok()) {
if (handler_) {
handler_(std::move(read_result));
}
// Schedule another read.
if (running_.load()) {
async::PostTask(dispatcher_, [this]() { AsyncReadWithHeader(); });
}
return ZX_OK;
}
switch (read_result.error_value()) {
case ZX_ERR_PEER_CLOSED: {
zxlogf(INFO, "The pipe server is closed. Read is cancelled.");
return read_result.error_value();
}
case ZX_ERR_SHOULD_WAIT: {
pipe_event().signal(/* clear_mask= */
fuchsia_hardware_goldfish::wire::kSignalHangup |
fuchsia_hardware_goldfish::wire::kSignalReadable,
0u);
wait_event_.set_object(pipe_event().get());
wait_event_.set_trigger(fuchsia_hardware_goldfish::wire::kSignalHangup |
fuchsia_hardware_goldfish::wire::kSignalReadable);
wait_event_.Begin(dispatcher_, [this](async_dispatcher_t* dispatcher, async::WaitOnce* wait,
zx_status_t status, const zx_packet_signal_t* signal) {
if (status == ZX_OK) {
AsyncReadWithHeader();
} else if (status == ZX_ERR_CANCELED) {
zxlogf(INFO, "AsyncReadWithHeader callback: wait event is canceled");
} else {
zxlogf(ERROR, "AsyncReadWithHeader callback: wait event error: %d", status);
}
});
return read_result.error_value();
}
default: {
ZX_ASSERT_MSG(false, "Unexpected Pipe IO error: %s",
zx_status_get_string(read_result.error_value()));
}
}
}
zx_status_t PipeAutoReader::BeginRead() {
running_.store(true);
return async::PostTask(dispatcher_, [this]() { AsyncReadWithHeader(); });
}
void PipeAutoReader::StopRead() {
running_.store(false);
wait_event_.Cancel();
}
} // namespace goldfish