blob: 366e1580aa049bc15b7023f346954d3e8c0c5f4b [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/netconnector_params.h"
#include <fuchsia/sys/cpp/fidl.h>
#include <rapidjson/document.h>
#include "garnet/lib/inet/ip_address.h"
#include "lib/fxl/files/file.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/split_string.h"
namespace netconnector {
namespace {
constexpr char kConfigServices[] = "services";
constexpr char kConfigDevices[] = "devices";
constexpr char kDefaultConfigFileName[] = "/pkg/data/netconnector.config";
} // namespace
NetConnectorParams::NetConnectorParams(const fxl::CommandLine& command_line) {
is_valid_ = false;
listen_ = command_line.HasOption("listen");
show_devices_ = command_line.HasOption("show-devices");
mdns_verbose_ = command_line.HasOption("mdns-verbose");
if (listen_ && show_devices_) {
FXL_LOG(ERROR) << "--listen and --show-devices are mutually exclusive";
Usage();
return;
}
std::string config_file_name;
if (!command_line.GetOptionValue("config", &config_file_name)) {
config_file_name = kDefaultConfigFileName;
}
if (config_file_name.empty()) {
Usage();
return;
}
if (listen_ && !ReadConfigFrom(config_file_name)) {
FXL_LOG(ERROR) << "Failed to parse config file " << config_file_name;
return;
}
is_valid_ = true;
}
void NetConnectorParams::Usage() {
FXL_LOG(INFO) << "netconnector usage:";
FXL_LOG(INFO) << " netconnector [ options ]";
FXL_LOG(INFO) << "options:";
FXL_LOG(INFO)
<< " --config=<file> read config file (default "
<< kDefaultConfigFileName << ")";
FXL_LOG(INFO) << " --show-devices show known devices";
FXL_LOG(INFO) << " --mdns-verbose log mDNS traffic";
FXL_LOG(INFO) << " --listen run as listener";
}
void NetConnectorParams::RegisterService(
const std::string& name, fuchsia::sys::LaunchInfoPtr launch_info) {
auto result =
launch_infos_by_service_name_.emplace(name, std::move(launch_info));
if (!result.second) {
FXL_DCHECK(result.first != launch_infos_by_service_name_.end());
result.first->second = std::move(launch_info);
}
}
void NetConnectorParams::RegisterDevice(const std::string& name,
const inet::IpAddress& address) {
auto result = device_addresses_by_name_.emplace(name, address);
if (!result.second) {
FXL_DCHECK(result.first != device_addresses_by_name_.end());
result.first->second = address;
}
}
void NetConnectorParams::UnregisterDevice(const std::string& name) {
device_addresses_by_name_.erase(name);
}
bool NetConnectorParams::ReadConfigFrom(const std::string& config_file_name) {
std::string config_file_contents;
return files::ReadFileToString(config_file_name, &config_file_contents) &&
ParseConfig(config_file_contents);
}
bool NetConnectorParams::ParseConfig(const std::string& string) {
rapidjson::Document document;
document.Parse(string.data(), string.size());
if (!document.IsObject())
return false;
auto iter = document.FindMember(kConfigServices);
if (iter != document.MemberEnd()) {
const auto& value = iter->value;
if (!value.IsObject()) {
return false;
}
for (const auto& pair : value.GetObject()) {
if (!pair.name.IsString()) {
return false;
}
auto launch_info = fuchsia::sys::LaunchInfo::New();
if (pair.value.IsString()) {
launch_info->url = pair.value.GetString();
} else if (pair.value.IsArray()) {
const auto& array = pair.value.GetArray();
if (array.Empty() || !array[0].IsString()) {
return false;
}
launch_info->url = array[0].GetString();
for (size_t i = 1; i < array.Size(); ++i) {
if (!array[i].IsString()) {
return false;
}
launch_info->arguments.push_back(array[i].GetString());
}
} else {
return false;
}
RegisterService(pair.name.GetString(), std::move(launch_info));
}
}
iter = document.FindMember(kConfigDevices);
if (iter != document.MemberEnd()) {
const auto& value = iter->value;
if (!value.IsObject()) {
return false;
}
for (const auto& pair : value.GetObject()) {
if (!pair.name.IsString() || !pair.value.IsString()) {
return false;
}
inet::IpAddress address =
inet::IpAddress::FromString(pair.value.GetString());
if (!address.is_valid()) {
FXL_LOG(ERROR) << "Config file contains invalid IP address "
<< pair.value.GetString();
return false;
}
RegisterDevice(pair.name.GetString(), address);
}
}
return true;
}
} // namespace netconnector