blob: ecaee4ad974a8b8bcf20f4c9af6ad9f5f4650771 [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 <lib/driver2/runtime_connector_impl.h>
#include <lib/fidl/llcpp/string_view.h>
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace {
class RuntimeProtocolIterator : public fidl::WireServer<fdf::RuntimeProtocolIterator> {
public:
static constexpr size_t kProtocolsBufferSize = 512;
explicit RuntimeProtocolIterator(std::unique_ptr<fidl::Arena<kProtocolsBufferSize>> arena,
std::vector<fidl::StringView> list)
: arena_(std::move(arena)), list_(std::move(list)) {}
void GetNext(GetNextRequestView request, GetNextCompleter::Sync& completer) {
constexpr size_t kMaxEntries = fdf::wire::kMaxProtocolsPerBatch;
auto result =
cpp20::span(list_.begin() + offset_, std::min(kMaxEntries, list_.size() - offset_));
offset_ += result.size();
completer.Reply(fidl::VectorView<fidl::StringView>::FromExternal(result.data(), result.size()));
}
private:
std::unique_ptr<fidl::Arena<kProtocolsBufferSize>> arena_;
size_t offset_ = 0;
std::vector<fidl::StringView> list_;
};
} // namespace
namespace driver {
void RuntimeConnectorImpl::RegisterProtocol(const std::string protocol_name,
RegisterProtocolHandler handler) {
protocol_to_handler_[protocol_name] = std::move(handler);
}
void RuntimeConnectorImpl::ListProtocols(ListProtocolsRequestView request,
ListProtocolsCompleter::Sync& completer) {
auto arena = std::make_unique<fidl::Arena<RuntimeProtocolIterator::kProtocolsBufferSize>>();
std::vector<fidl::StringView> protocols;
for (auto& iter : protocol_to_handler_) {
fidl::StringView sv(*arena, iter.first);
protocols.push_back(std::move(sv));
}
auto iterator = std::make_unique<RuntimeProtocolIterator>(std::move(arena), std::move(protocols));
fidl::BindServer(dispatcher_, std::move(request->iterator), std::move(iterator));
}
void RuntimeConnectorImpl::Connect(ConnectRequestView request, ConnectCompleter::Sync& completer) {
fdf::Channel channel(request->runtime_protocol.handle);
auto protocol_name = std::string(request->protocol_name.data(), request->protocol_name.size());
auto it = protocol_to_handler_.find(protocol_name);
if (it == protocol_to_handler_.end()) {
completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
return;
}
auto& handler = it->second;
zx_status_t status = handler(std::move(channel));
if (status != ZX_OK) {
completer.ReplyError(status);
return;
}
completer.ReplySuccess();
}
} // namespace driver