blob: fef8f8df619a2f20d147b20d629b61fb879142ee [file] [log] [blame]
// Copyright 2016 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 "garnet/bin/netconnector/responding_service_host.h"
#include "lib/fidl/cpp/clone.h"
#include "src/lib/fxl/logging.h"
namespace netconnector {
RespondingServiceHost::RespondingServiceHost(
const fuchsia::sys::EnvironmentPtr& environment) {
FXL_DCHECK(environment);
environment->GetLauncher(launcher_.NewRequest());
}
RespondingServiceHost::~RespondingServiceHost() {}
void RespondingServiceHost::RegisterSingleton(
const std::string& service_name, fuchsia::sys::LaunchInfoPtr launch_info) {
service_namespace_.AddServiceForName(
[this, service_name, launch_info = std::move(launch_info)](
zx::channel client_handle) mutable {
FXL_VLOG(2) << "Handling request for service " << service_name;
auto iter = service_providers_by_name_.find(service_name);
if (iter == service_providers_by_name_.end()) {
FXL_VLOG(1) << "Launching " << launch_info->url << " for service "
<< service_name;
// TODO(dalesat): Create application-specific environment.
// We're launching this application in the environment supplied to
// the constructor. Instead, we should be launching it in a new
// environment that is restricted based on app permissions.
fuchsia::sys::LaunchInfo dup_launch_info;
dup_launch_info.url = launch_info->url;
fidl::Clone(launch_info->arguments, &dup_launch_info.arguments);
component::Services services;
dup_launch_info.directory_request = services.NewRequest();
fuchsia::sys::ComponentControllerPtr controller;
launcher_->CreateComponent(std::move(dup_launch_info),
controller.NewRequest());
controller.set_error_handler(
[this, service_name](zx_status_t status) {
FXL_LOG(INFO)
<< "Service " << service_name << " provider disconnected";
service_providers_by_name_.erase(service_name);
});
std::tie(iter, std::ignore) = service_providers_by_name_.emplace(
std::make_pair<const std::string&, ServicesHolder>(
service_name, {std::move(services), std::move(controller)}));
}
iter->second.ConnectToService(service_name, std::move(client_handle));
},
service_name);
}
void RespondingServiceHost::RegisterProvider(
const std::string& service_name,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> handle) {
fuchsia::sys::ServiceProviderPtr service_provider = handle.Bind();
service_provider.set_error_handler([this, service_name](zx_status_t status) {
FXL_LOG(INFO) << "Service " << service_name << " provider disconnected";
service_providers_by_name_.erase(service_name);
});
service_providers_by_name_.emplace(service_name, std::move(service_provider));
service_namespace_.AddServiceForName(
[this, service_name](zx::channel client_handle) {
FXL_VLOG(2) << "Servicing provided service request for "
<< service_name;
auto iter = service_providers_by_name_.find(service_name);
FXL_DCHECK(iter != service_providers_by_name_.end());
iter->second.ConnectToService(service_name, std::move(client_handle));
},
service_name);
}
void RespondingServiceHost::ServicesHolder::ConnectToService(
const std::string& service_name, zx::channel c) {
if (is_service_provider_) {
service_provider_->ConnectToService(service_name, std::move(c));
return;
}
services_.ConnectToService(std::move(c), service_name);
}
} // namespace netconnector