blob: 59ff0e8f3845972168f133211d7e07fa930a4aa9 [file] [log] [blame]
// Copyright 2020 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 "bootstrap_fidl_impl.h"
#include <lib/async/cpp/task.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include <src/lib/files/file.h>
#include <src/lib/fsl/vmo/strings.h>
#include "thread_config_manager.h"
namespace ot {
namespace Fuchsia {
namespace {
constexpr char kMigrationConfigPath[] = "/config/data/migration_config.json";
} // namespace
// BootstrapThreadImpl definitions -------------------------------------------------------
BootstrapThreadImpl::BootstrapThreadImpl() {}
BootstrapThreadImpl::~BootstrapThreadImpl() {
StopServingFidl();
if (binding_) {
// If server is getting destroyed when there is
// still an active binding, close binding with epitaph
// informing client that the server has closed down:
CloseBinding(ZX_ERR_PEER_CLOSED);
}
}
zx_status_t BootstrapThreadImpl::Bind(fidl::ServerEnd<fuchsia_lowpan_bootstrap::Thread> request,
async_dispatcher_t* dispatcher,
cpp17::optional<const fbl::RefPtr<fs::PseudoDir>> svc_dir) {
if (!ShouldServe()) {
return ZX_OK;
}
binding_ = fidl::BindServer(dispatcher, std::move(request), this);
// Note the svc_dir_ with which AddEntry was done, so that RemoveEntry can
// be done when we want to stop serving this FIDL:
svc_dir_ = svc_dir;
return ZX_OK;
}
void BootstrapThreadImpl::StopServingFidl() {
if (svc_dir_) {
FX_LOGS(INFO) << "Removing svc entry";
svc_dir_.value()->RemoveEntry(fuchsia_lowpan_bootstrap::Thread::Name);
svc_dir_.reset();
}
}
void BootstrapThreadImpl::CloseBinding(zx_status_t close_binding_status) {
if (binding_) {
FX_LOGS(INFO) << "Closing server binding";
binding_->Close(close_binding_status);
binding_.reset();
}
}
void BootstrapThreadImpl::CloseBinding(zx_status_t close_binding_status,
ImportSettingsCompleter::Sync& completer) {
if (binding_) {
FX_LOGS(INFO) << "Closing server binding";
completer.Close(close_binding_status);
binding_.reset();
}
}
void BootstrapThreadImpl::ImportSettings(fuchsia_mem::wire::Buffer thread_settings_json,
ImportSettingsCompleter::Sync& completer) {
std::string data;
fsl::SizedVmo sized_vmo(std::move(thread_settings_json.vmo), thread_settings_json.size);
if (!fsl::StringFromVmo(sized_vmo, &data)) {
FX_LOGS(ERROR) << "Failed to get data from VMO.";
StopServingFidl();
CloseBinding(ZX_ERR_IO, completer);
return;
}
if (!files::WriteFile(GetSettingsPath(), data.data(), data.size())) {
FX_LOGS(ERROR) << "Failed to write data to internal config location";
StopServingFidl();
CloseBinding(ZX_ERR_IO, completer);
return;
}
completer.Reply();
FX_LOGS(INFO) << "Done with ImportSettings!";
StopServingFidl();
CloseBinding(ZX_OK);
}
bool BootstrapThreadImpl::ShouldServe() { return files::IsFile(kMigrationConfigPath); }
std::string BootstrapThreadImpl::GetSettingsPath() { return kThreadSettingsPath; }
} // namespace Fuchsia
} // namespace ot