buffet: Start privet logic Initialize privetd::Manager from buffet::Manager. Added flag disable_privet to disable local APIs. CloudDelegate still uses D-Bus to communicate with buffet. BUG=brillo:1161 TEST=`FEATURES=test emerge-gizmo buffet` Change-Id: Ic5d687f0e45d9be3c487a2f2b2de354f4b437441 Reviewed-on: https://chromium-review.googlesource.com/276602 Reviewed-by: Alex Vakulenko <avakulenko@chromium.org> Reviewed-by: Vitaly Buka <vitalybuka@chromium.org> Commit-Queue: Vitaly Buka <vitalybuka@chromium.org> Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/etc/init/buffet.conf b/buffet/etc/init/buffet.conf index ba4adb2..bd273c1 100644 --- a/buffet/etc/init/buffet.conf +++ b/buffet/etc/init/buffet.conf
@@ -14,6 +14,10 @@ env BUFFET_STATE_PATH= env BUFFET_CONFIG_PATH= env BUFFET_TEST_DEFINITIONS_PATH= +env BUFFET_ENABLE_PING=false +env BUFFET_DISABLE_SECURITY=false +env BUFFET_DEVICE_WHITELIST= +env BUFFET_DISABLE_PRIVET=false pre-start script mkdir -m 0755 -p /var/lib/buffet @@ -28,7 +32,11 @@ --config_path="${BUFFET_CONFIG_PATH}" \ --state_path="${BUFFET_STATE_PATH}" \ --test_definitions_path="${BUFFET_TEST_DEFINITIONS_PATH}" \ - --enable_xmpp="${BUFFET_ENABLE_XMPP}" + --enable_xmpp="${BUFFET_ENABLE_XMPP}" \ + --disable_security="${BUFFET_DISABLE_SECURITY}" \ + --enable_ping="${BUFFET_ENABLE_PING}" \ + --device_whitelist="${BUFFET_DEVICE_WHITELIST}" \ + --disable_privet="${BUFFET_DISABLE_PRIVET}" # Wait for daemon to claim its D-Bus name before transitioning to started. post-start exec gdbus wait --system --timeout 30 org.chromium.Buffet
diff --git a/buffet/main.cc b/buffet/main.cc index c7d44d0..3971abb 100644 --- a/buffet/main.cc +++ b/buffet/main.cc
@@ -9,6 +9,7 @@ #include <chromeos/dbus/exported_object_manager.h> #include <chromeos/daemons/dbus_daemon.h> #include <chromeos/flag_helper.h> +#include <chromeos/strings/string_utils.h> #include <chromeos/syslog_logging.h> #include "buffet/dbus_constants.h" @@ -23,31 +24,20 @@ class Daemon final : public DBusServiceDaemon { public: - Daemon(const base::FilePath& config_path, - const base::FilePath& state_path, - const base::FilePath& test_definitions_path, - bool enable_xmpp) - : DBusServiceDaemon(kServiceName, kRootServicePath), - config_path_{config_path}, - state_path_{state_path}, - test_definitions_path_{test_definitions_path}, - enable_xmpp_{enable_xmpp} {} + explicit Daemon(const buffet::Manager::Options& options) + : DBusServiceDaemon(kServiceName, kRootServicePath), options_{options} {} protected: void RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) override { manager_.reset(new buffet::Manager(object_manager_->AsWeakPtr())); - manager_->Start( - config_path_, state_path_, test_definitions_path_, enable_xmpp_, - sequencer->GetHandler("Manager.RegisterAsync() failed.", true)); + manager_->Start(options_, sequencer); } - private: - std::unique_ptr<buffet::Manager> manager_; - const base::FilePath config_path_; - const base::FilePath state_path_; - const base::FilePath test_definitions_path_; - const bool enable_xmpp_; + void OnShutdown(int* return_code) override { manager_->Stop(); } + private: + buffet::Manager::Options options_; + std::unique_ptr<buffet::Manager> manager_; DISALLOW_COPY_AND_ASSIGN(Daemon); }; @@ -71,6 +61,12 @@ "and state definitions. For use in test only."); DEFINE_bool(enable_xmpp, true, "Connect to GCD via a persistent XMPP connection."); + DEFINE_bool(disable_privet, false, "disable Privet protocol"); + DEFINE_bool(disable_security, false, "disable Privet security for tests"); + DEFINE_bool(enable_ping, false, "enable test HTTP handler at /privet/ping"); + DEFINE_string(device_whitelist, "", + "Comma separated list of network interfaces to monitor for " + "connectivity (an empty list enables all interfaces)."); chromeos::FlagHelper::Init(argc, argv, "Privet protocol handler daemon"); if (FLAGS_config_path.empty()) FLAGS_config_path = kDefaultConfigFilePath; @@ -81,9 +77,20 @@ flags |= chromeos::kLogToStderr; chromeos::InitLog(flags); - buffet::Daemon daemon{base::FilePath{FLAGS_config_path}, - base::FilePath{FLAGS_state_path}, - base::FilePath{FLAGS_test_definitions_path}, - FLAGS_enable_xmpp}; + auto device_whitelist = + chromeos::string_utils::Split(FLAGS_device_whitelist, ",", true, true); + + buffet::Manager::Options options; + options.config_path = base::FilePath{FLAGS_config_path}; + options.state_path = base::FilePath{FLAGS_state_path}; + options.test_definitions_path = base::FilePath{FLAGS_test_definitions_path}; + options.xmpp_enabled = FLAGS_enable_xmpp; + options.privet.disable_privet = FLAGS_disable_privet; + options.privet.disable_security = FLAGS_disable_security; + options.privet.enable_ping = FLAGS_enable_ping; + options.privet.device_whitelist.insert(device_whitelist.begin(), + device_whitelist.end()); + + buffet::Daemon daemon{options}; return daemon.Run(); }
diff --git a/buffet/manager.cc b/buffet/manager.cc index 5b6a6e5..d9ddfaf 100644 --- a/buffet/manager.cc +++ b/buffet/manager.cc
@@ -59,27 +59,23 @@ Manager::~Manager() { } -void Manager::Start(const base::FilePath& config_path, - const base::FilePath& state_path, - const base::FilePath& test_definitions_path, - bool xmpp_enabled, - const AsyncEventSequencer::CompletionAction& cb) { +void Manager::Start(const Options& options, AsyncEventSequencer* sequencer) { command_manager_ = std::make_shared<CommandManager>(dbus_object_.GetObjectManager()); command_manager_->AddOnCommandDefChanged(base::Bind( &Manager::OnCommandDefsChanged, weak_ptr_factory_.GetWeakPtr())); command_manager_->Startup(base::FilePath{"/etc/buffet"}, - test_definitions_path); + options.test_definitions_path); state_change_queue_.reset(new StateChangeQueue(kMaxStateChangeQueueSize)); state_manager_ = std::make_shared<StateManager>(state_change_queue_.get()); state_manager_->AddOnChangedCallback( base::Bind(&Manager::OnStateChanged, weak_ptr_factory_.GetWeakPtr())); state_manager_->Startup(); - std::unique_ptr<BuffetConfig> config{new BuffetConfig{state_path}}; + std::unique_ptr<BuffetConfig> config{new BuffetConfig{options.state_path}}; config->AddOnChangedCallback( base::Bind(&Manager::OnConfigChanged, weak_ptr_factory_.GetWeakPtr())); - config->Load(config_path); + config->Load(options.config_path); auto transport = chromeos::http::Transport::CreateDefault(); transport->SetDefaultTimeout(base::TimeDelta::FromSeconds( @@ -89,7 +85,7 @@ // device info state data unencrypted. device_info_.reset(new DeviceRegistrationInfo( command_manager_, state_manager_, std::move(config), transport, - xmpp_enabled)); + options.xmpp_enabled)); device_info_->AddOnRegistrationChangedCallback(base::Bind( &Manager::OnRegistrationChanged, weak_ptr_factory_.GetWeakPtr())); @@ -97,8 +93,36 @@ device_info_->AsWeakPtr(), state_manager_, command_manager_}); device_info_->Start(); + dbus_adaptor_.RegisterWithDBusObject(&dbus_object_); - dbus_object_.RegisterAsync(cb); + dbus_object_.RegisterAsync( + sequencer->GetHandler("Manager.RegisterAsync() failed.", true)); + + if (!options.privet.disable_privet) + StartPrivet(options.privet, sequencer); +} + +void Manager::StartPrivet(const privetd::Manager::Options& options, + AsyncEventSequencer* sequencer) { + privet_.reset(new privetd::Manager{}); + privet_->Start(options, dbus_object_.GetBus(), sequencer); + + if (privet_->GetWifiBootstrapManager()) { + privet_->GetWifiBootstrapManager()->RegisterStateListener(base::Bind( + &Manager::UpdateWiFiBootstrapState, weak_ptr_factory_.GetWeakPtr())); + } else { + UpdateWiFiBootstrapState(privetd::WifiBootstrapManager::kDisabled); + } + + privet_->GetSecurityManager()->RegisterPairingListeners( + base::Bind(&Manager::OnPairingStart, weak_ptr_factory_.GetWeakPtr()), + base::Bind(&Manager::OnPairingEnd, weak_ptr_factory_.GetWeakPtr())); + // TODO(wiley) Watch for appropriate state variables from |cloud_delegate|. +} + +void Manager::Stop() { + if (privet_) + privet_->OnShutdown(); } void Manager::CheckDeviceRegistered(DBusMethodResponse<std::string> response) {
diff --git a/buffet/manager.h b/buffet/manager.h index 781fa03..2f8fd66 100644 --- a/buffet/manager.h +++ b/buffet/manager.h
@@ -52,12 +52,18 @@ object_manager); ~Manager(); - void Start( - const base::FilePath& config_path, - const base::FilePath& state_path, - const base::FilePath& test_definitions_path, - bool xmpp_enabled, - const chromeos::dbus_utils::AsyncEventSequencer::CompletionAction& cb); + struct Options { + base::FilePath config_path; + base::FilePath state_path; + base::FilePath test_definitions_path; + bool xmpp_enabled{true}; + privetd::Manager::Options privet; + }; + + void Start(const Options& options, + chromeos::dbus_utils::AsyncEventSequencer* sequencer); + + void Stop(); private: // DBus methods: @@ -99,6 +105,9 @@ const chromeos::VariantDictionary& in_options) override; bool DisableGCDBootstrapping(chromeos::ErrorPtr* error) override; + void StartPrivet(const privetd::Manager::Options& options, + chromeos::dbus_utils::AsyncEventSequencer* sequencer); + void OnCommandDefsChanged(); void OnStateChanged(); void OnRegistrationChanged(RegistrationStatus status); @@ -117,6 +126,7 @@ std::shared_ptr<StateManager> state_manager_; std::unique_ptr<DeviceRegistrationInfo> device_info_; std::unique_ptr<BaseApiHandler> base_api_handler_; + std::unique_ptr<privetd::Manager> privet_; base::WeakPtrFactory<Manager> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(Manager);
diff --git a/buffet/privet/cloud_delegate.cc b/buffet/privet/cloud_delegate.cc index 5003c9d..653bf5d 100644 --- a/buffet/privet/cloud_delegate.cc +++ b/buffet/privet/cloud_delegate.cc
@@ -509,8 +509,10 @@ // static std::unique_ptr<CloudDelegate> CloudDelegate::CreateDefault( - const scoped_refptr<dbus::Bus>& bus, bool is_gcd_setup_enabled) { + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SYSTEM; + scoped_refptr<dbus::Bus> bus{new dbus::Bus{options}}; return std::unique_ptr<CloudDelegateImpl>{ new CloudDelegateImpl{bus, is_gcd_setup_enabled}}; }
diff --git a/buffet/privet/cloud_delegate.h b/buffet/privet/cloud_delegate.h index 0d027f9..75d0a63 100644 --- a/buffet/privet/cloud_delegate.h +++ b/buffet/privet/cloud_delegate.h
@@ -131,7 +131,6 @@ // Create default instance. static std::unique_ptr<CloudDelegate> CreateDefault( - const scoped_refptr<dbus::Bus>& bus, bool is_gcd_setup_enabled); private:
diff --git a/buffet/privet/privet_manager.cc b/buffet/privet/privet_manager.cc index 36aaa7e..1471404 100644 --- a/buffet/privet/privet_manager.cc +++ b/buffet/privet/privet_manager.cc
@@ -7,7 +7,6 @@ #include <memory> #include <set> #include <string> -#include <sysexits.h> #include <base/bind.h> #include <base/command_line.h> @@ -39,6 +38,7 @@ #include "buffet/privet/security_manager.h" #include "buffet/privet/shill_client.h" #include "buffet/privet/wifi_bootstrap_manager.h" +#include "buffet/dbus_constants.h" namespace privetd { @@ -57,59 +57,60 @@ return headers.empty() ? std::string() : headers.front(); } -const char kServiceName[] = "org.chromium.privetd"; -const char kRootPath[] = "/org/chromium/privetd"; - } // namespace -Manager::Manager(bool disable_security, - bool enable_ping, - const std::set<std::string>& device_whitelist, - const base::FilePath& config_path, - const base::FilePath& state_path) - : DBusServiceDaemon(kServiceName, kRootPath), - disable_security_(disable_security), - enable_ping_(enable_ping), - device_whitelist_(device_whitelist), - config_path_(config_path), - state_store_(new DaemonState(state_path)) { +Manager::Manager() { } -void Manager::RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) { +Manager::~Manager() { +} + +void Manager::Start(const Options& options, + const scoped_refptr<dbus::Bus>& bus, + AsyncEventSequencer* sequencer) { + disable_security_ = options.disable_security; + + // TODO(vitalybuka): switch to BuffetConfig. + base::FilePath config_path{privetd::kDefaultConfigFilePath}; + base::FilePath state_path{privetd::kDefaultStateFilePath}; + + state_store_.reset(new DaemonState(state_path)); parser_.reset(new PrivetdConfigParser); chromeos::KeyValueStore config_store; - if (!config_store.Load(config_path_)) { + if (!config_store.Load(config_path)) { LOG(ERROR) << "Failed to read privetd config file from " - << config_path_.value(); + << config_path.value(); } else { CHECK(parser_->Parse(config_store)) << "Failed to read configuration file."; } state_store_->Init(); + + std::set<std::string> device_whitelist{options.device_whitelist}; // This state store key doesn't exist naturally, but developers // sometime put it in their state store to cause the device to bring // up WiFi bootstrapping while being connected to an ethernet interface. std::string test_device_whitelist; - if (device_whitelist_.empty() && + if (device_whitelist.empty() && state_store_->GetString(kWiFiBootstrapInterfaces, &test_device_whitelist)) { auto interfaces = chromeos::string_utils::Split(test_device_whitelist, ",", true, true); - device_whitelist_.insert(interfaces.begin(), interfaces.end()); + device_whitelist.insert(interfaces.begin(), interfaces.end()); } device_ = DeviceDelegate::CreateDefault(); - cloud_ = CloudDelegate::CreateDefault( - bus_, parser_->gcd_bootstrap_mode() != GcdBootstrapMode::kDisabled); + cloud_ = CloudDelegate::CreateDefault(parser_->gcd_bootstrap_mode() != + GcdBootstrapMode::kDisabled); cloud_observer_.Add(cloud_.get()); security_.reset(new SecurityManager(parser_->pairing_modes(), parser_->embedded_code_path(), disable_security_)); shill_client_.reset(new ShillClient( - bus_, device_whitelist_.empty() ? parser_->automatic_wifi_interfaces() - : device_whitelist_)); + bus, device_whitelist.empty() ? parser_->automatic_wifi_interfaces() + : device_whitelist)); shill_client_->RegisterConnectivityListener( base::Bind(&Manager::OnConnectivityChanged, base::Unretained(this))); - ap_manager_client_.reset(new ApManagerClient(bus_)); + ap_manager_client_.reset(new ApManagerClient(bus)); if (parser_->wifi_bootstrap_mode() != WiFiBootstrapMode::kDisabled) { VLOG(1) << "Enabling WiFi bootstrapping."; @@ -121,19 +122,20 @@ wifi_bootstrap_manager_->Init(); } - peerd_client_.reset(new PeerdClient(bus_, device_.get(), cloud_.get(), + peerd_client_.reset(new PeerdClient(bus, device_.get(), cloud_.get(), wifi_bootstrap_manager_.get())); privet_handler_.reset( new PrivetHandler(cloud_.get(), device_.get(), security_.get(), wifi_bootstrap_manager_.get(), peerd_client_.get())); + web_server_.reset(new libwebserv::Server); web_server_->OnProtocolHandlerConnected(base::Bind( &Manager::OnProtocolHandlerConnected, weak_ptr_factory_.GetWeakPtr())); web_server_->OnProtocolHandlerDisconnected(base::Bind( &Manager::OnProtocolHandlerDisconnected, weak_ptr_factory_.GetWeakPtr())); - web_server_->Connect(bus_, kServiceName, + web_server_->Connect(bus, buffet::dbus_constants::kServiceName, sequencer->GetHandler("Server::Connect failed.", true), base::Bind(&base::DoNothing), base::Bind(&base::DoNothing)); @@ -144,7 +146,7 @@ web_server_->GetDefaultHttpsHandler()->AddHandlerCallback( "/privet/", "", base::Bind(&Manager::PrivetRequestHandler, base::Unretained(this))); - if (enable_ping_) { + if (options.enable_ping) { web_server_->GetDefaultHttpHandler()->AddHandlerCallback( "/privet/ping", chromeos::http::request_type::kGet, base::Bind(&Manager::HelloWorldHandler, base::Unretained(this))); @@ -154,14 +156,13 @@ } } -void Manager::OnShutdown(int* return_code) { +void Manager::OnShutdown() { web_server_->Disconnect(); - DBusDaemon::OnShutdown(return_code); } void Manager::OnDeviceInfoChanged() { OnChanged(); -} +}; void Manager::PrivetRequestHandler(std::unique_ptr<Request> request, std::unique_ptr<Response> response) { @@ -240,38 +241,3 @@ } } // namespace privetd - -int old_main(int argc, char* argv[]) { - DEFINE_bool(disable_security, false, "disable Privet security for tests"); - DEFINE_bool(enable_ping, false, "enable test HTTP handler at /privet/ping"); - DEFINE_bool(log_to_stderr, false, "log trace messages to stderr as well"); - DEFINE_string(config_path, privetd::kDefaultConfigFilePath, - "Path to file containing config information."); - DEFINE_string(state_path, privetd::kDefaultStateFilePath, - "Path to file containing state information."); - DEFINE_string(device_whitelist, "", - "Comma separated list of network interfaces to monitor for " - "connectivity (an empty list enables all interfaces)."); - - chromeos::FlagHelper::Init(argc, argv, "Privet protocol handler daemon"); - - int flags = chromeos::kLogToSyslog; - if (FLAGS_log_to_stderr) - flags |= chromeos::kLogToStderr; - chromeos::InitLog(flags | chromeos::kLogHeader); - - if (FLAGS_config_path.empty()) - FLAGS_config_path = privetd::kDefaultConfigFilePath; - - if (FLAGS_state_path.empty()) - FLAGS_state_path = privetd::kDefaultStateFilePath; - - auto device_whitelist = - chromeos::string_utils::Split(FLAGS_device_whitelist, ",", true, true); - - privetd::Manager daemon( - FLAGS_disable_security, FLAGS_enable_ping, - std::set<std::string>(device_whitelist.begin(), device_whitelist.end()), - base::FilePath(FLAGS_config_path), base::FilePath(FLAGS_state_path)); - return daemon.Run(); -}
diff --git a/buffet/privet/privet_manager.h b/buffet/privet/privet_manager.h index 23e19d4..8130b9d 100644 --- a/buffet/privet/privet_manager.h +++ b/buffet/privet/privet_manager.h
@@ -12,10 +12,14 @@ #include <base/memory/weak_ptr.h> #include <base/scoped_observer.h> -#include <chromeos/daemons/dbus_daemon.h> #include "buffet/privet/cloud_delegate.h" +namespace buffet { +class CommandManager; +class DeviceRegistrationInfo; +} + namespace chromeos { namespace dbus_utils { class AsyncEventSequencer; @@ -31,34 +35,43 @@ namespace privetd { -class PrivetdConfigParser; -class DaemonState; -class CloudDelegate; -class DeviceDelegate; -class SecurityManager; -class ShillClient; class ApManagerClient; -class WifiBootstrapManager; +class CloudDelegate; +class DaemonState; +class DeviceDelegate; class PeerdClient; class PrivetHandler; +class PrivetdConfigParser; +class SecurityManager; +class ShillClient; +class WifiBootstrapManager; -class Manager : public chromeos::DBusServiceDaemon, - public CloudDelegate::Observer { +class Manager : public CloudDelegate::Observer { public: - Manager(bool disable_security, - bool enable_ping, - const std::set<std::string>& device_whitelist, - const base::FilePath& config_path, - const base::FilePath& state_path); - ~Manager() override; + struct Options { + bool disable_privet{false}; + bool disable_security{false}; + bool enable_ping{false}; + std::set<std::string> device_whitelist; + }; - void RegisterDBusObjectsAsync( - chromeos::dbus_utils::AsyncEventSequencer* sequencer) override; + Manager(); + ~Manager(); - void OnShutdown(int* return_code) override; + void Start(const Options& options, + const scoped_refptr<dbus::Bus>& bus, + chromeos::dbus_utils::AsyncEventSequencer* sequencer); + + void OnShutdown(); void OnDeviceInfoChanged() override; + privetd::WifiBootstrapManager* GetWifiBootstrapManager() { + return wifi_bootstrap_manager_.get(); + } + + privetd::SecurityManager* GetSecurityManager() { return security_.get(); } + private: void PrivetRequestHandler(std::unique_ptr<libwebserv::Request> request, std::unique_ptr<libwebserv::Response> response); @@ -80,11 +93,8 @@ void OnProtocolHandlerDisconnected( libwebserv::ProtocolHandler* protocol_handler); - bool disable_security_; - bool enable_ping_; + bool disable_security_{false}; std::unique_ptr<PrivetdConfigParser> parser_; - std::set<std::string> device_whitelist_; - base::FilePath config_path_; std::unique_ptr<DaemonState> state_store_; std::unique_ptr<CloudDelegate> cloud_; std::unique_ptr<DeviceDelegate> device_;