blob: 67b37b4c1d1d449f67e6c0f6a26320cba6b1926d [file] [log] [blame]
// Copyright 2017 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/svc/cpp/service_provider_bridge.h"
#include <fcntl.h>
#include <fdio/util.h>
#include <zircon/device/vfs.h>
#include <utility>
#include "lib/fsl/tasks/message_loop.h"
namespace app {
ServiceProviderBridge::ServiceProviderBridge()
: vfs_(fsl::MessageLoop::GetCurrent()->async()),
directory_(fbl::AdoptRef(new svcfs::VnodeProviderDir())) {
directory_->SetServiceProvider(this);
}
ServiceProviderBridge::~ServiceProviderBridge() {
directory_->SetServiceProvider(nullptr);
}
void ServiceProviderBridge::AddBinding(
fidl::InterfaceRequest<app::ServiceProvider> request) {
bindings_.AddBinding(this, std::move(request));
}
void ServiceProviderBridge::AddServiceForName(ServiceConnector connector,
const std::string& service_name) {
name_to_service_connector_[service_name] = std::move(connector);
}
bool ServiceProviderBridge::ServeDirectory(zx::channel channel) {
return vfs_.ServeDirectory(directory_, std::move(channel)) == ZX_OK;
}
zx::channel ServiceProviderBridge::OpenAsDirectory() {
zx::channel h1, h2;
if (zx::channel::create(0, &h1, &h2) < 0)
return zx::channel();
if (!ServeDirectory(std::move(h1)))
return zx::channel();
return h2;
}
int ServiceProviderBridge::OpenAsFileDescriptor() {
zx::channel h1, h2;
if (zx::channel::create(0, &h1, &h2) < 0)
return -1;
if (!ServeDirectory(std::move(h1)))
return -1;
fdio_t* io = fdio_remote_create(h2.release(), ZX_HANDLE_INVALID);
if (!io)
return -1;
return fdio_bind_to_fd(io, -1, 0);
}
void ServiceProviderBridge::Connect(const char* name,
size_t len,
zx::channel channel) {
ConnectToService(fidl::String(name, len), std::move(channel));
}
void ServiceProviderBridge::ConnectToService(const fidl::String& service_name,
zx::channel channel) {
auto it = name_to_service_connector_.find(service_name.get());
if (it != name_to_service_connector_.end())
it->second(std::move(channel));
else
backend_->ConnectToService(std::move(service_name), std::move(channel));
}
} // namespace app