blob: c88ba935a63748b292b151d88a76d24e20587919 [file] [log] [blame]
// Copyright 2022 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/sys/fuzzing/common/corpus-reader-client.h"
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include "src/sys/fuzzing/common/async-socket.h"
namespace fuzzing {
CorpusReaderClient::CorpusReaderClient(ExecutorPtr executor) : executor_(std::move(executor)) {}
fidl::InterfaceRequest<CorpusReader> CorpusReaderClient::NewRequest() {
return ptr_.NewRequest(executor_->dispatcher());
}
void CorpusReaderClient::Bind(fidl::InterfaceHandle<CorpusReader> handle) {
auto status = ptr_.Bind(std::move(handle), executor_->dispatcher());
FX_CHECK(status == ZX_OK) << zx_status_get_string(status);
}
ZxPromise<> CorpusReaderClient::Send(std::vector<Input> inputs) {
// Create sockets for all non-empty inputs, plus one final empty sentinel input.
std::deque<FidlInput> fidl_inputs;
for (const auto& input : inputs) {
if (input.size()) {
fidl_inputs.emplace_back(AsyncSocketWrite(executor_, input));
}
}
fidl_inputs.emplace_back(AsyncSocketWrite(executor_, Input()));
// Create a future which sends data to each socket in turn.
ZxBridge<> outer;
auto task =
fpromise::make_promise([this, fidl_inputs = std::move(fidl_inputs),
sending = ZxFuture<>()](Context& context) mutable -> ZxResult<> {
while (true) {
if (fidl_inputs.empty()) {
return fpromise::ok();
}
if (!sending) {
Bridge<zx_status_t> inner;
ptr_->Next(std::move(fidl_inputs.front()), inner.completer.bind());
sending = ConsumeBridge(inner);
}
if (!sending(context)) {
return fpromise::pending();
}
if (sending.is_error()) {
return fpromise::error(sending.error());
}
sending = nullptr;
fidl_inputs.pop_front();
}
})
.then([callback = ZxBind<>(std::move(outer.completer))](ZxResult<>& result) {
if (result.is_error()) {
FX_LOGS(WARNING) << "Failed to send corpus: " << zx_status_get_string(result.error());
}
callback(result);
})
.wrap_with(scope_);
executor_->schedule_task(std::move(task));
return ConsumeBridge(outer);
}
} // namespace fuzzing