buffet: Remove libbuffet and rely on generated proxies
libbuffet functionality is no longer needed since the D-Bus code
generator is sufficient to provide the fully-functional proxy
objects for commands and buffet's object manager.
Also pretty much rewrote buffet_client. A lot of D-Bus
functionality in libchrome relies on the message loop and
asyncronous operations (e.g. Object Manager is constructed
asyncronously and it would crash if there is no message loop
for the main thread). So, made the buffet_client a "real"
application with a message loop that sends D-Bus requests
asynchronously.
BUG=chromium:431737
TEST=FEATURES=test emerge-link buffet
CQ-DEPEND=CL:232850
Change-Id: Ibf53369b502efa9b9d0e233fbcdf3331993e4f6a
Reviewed-on: https://chromium-review.googlesource.com/232533
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/buffet_client.cc b/buffet/buffet_client.cc
index 3edbbc3..ca91cee 100644
--- a/buffet/buffet_client.cc
+++ b/buffet/buffet_client.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <iostream> // NOLINT(readability/streams)
#include <memory>
#include <string>
#include <sysexits.h>
@@ -10,8 +9,10 @@
#include <base/command_line.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
+#include <base/strings/stringprintf.h>
#include <base/values.h>
#include <chromeos/any.h>
+#include <chromeos/daemons/dbus_daemon.h>
#include <chromeos/data_encoding.h>
#include <chromeos/dbus/data_serialization.h>
#include <chromeos/dbus/dbus_method_invoker.h>
@@ -24,137 +25,183 @@
#include <dbus/values_util.h>
#include "buffet/dbus-proxies.h"
-#include "buffet/libbuffet/dbus_constants.h"
-using namespace buffet::dbus_constants; // NOLINT(build/namespaces)
-
-using chromeos::dbus_utils::CallMethodAndBlock;
-using chromeos::dbus_utils::CallMethodAndBlockWithTimeout;
-using chromeos::dbus_utils::ExtractMethodCallResults;
-using chromeos::VariantDictionary;
+using chromeos::Error;
using chromeos::ErrorPtr;
namespace {
void usage() {
- std::cerr << "Possible commands:" << std::endl;
- std::cerr << " " << kManagerTestMethod << " <message>" << std::endl;
- std::cerr << " " << kManagerStartDevice << std::endl;
- std::cerr << " " << kManagerCheckDeviceRegistered << std::endl;
- std::cerr << " " << kManagerGetDeviceInfo << std::endl;
- std::cerr << " " << kManagerRegisterDevice
- << " param1 = val1¶m2 = val2..." << std::endl;
- std::cerr << " " << kManagerAddCommand
- << " '{\"name\":\"command_name\",\"parameters\":{}}'"
- << std::endl;
- std::cerr << " " << kManagerUpdateStateMethod
- << " prop_name prop_value" << std::endl;
- std::cerr << " " << dbus::kObjectManagerGetManagedObjects << std::endl;
+ printf(R"(Possible commands:
+ - TestMethod <message>
+ - StartDevice
+ - CheckDeviceRegistered
+ - GetDeviceInfo
+ - RegisterDevice param1=val1¶m2=val2...
+ - AddCommand '{"name":"command_name","parameters":{}}'
+ - UpdateStateMethod prop_name prop_value
+ - PendingCommands
+)");
}
-class BuffetHelperProxy {
+class Daemon : public chromeos::DBusDaemon {
public:
- int Init() {
- dbus::Bus::Options options;
- options.bus_type = dbus::Bus::SYSTEM;
- bus_ = new dbus::Bus(options);
+ Daemon() = default;
+
+ protected:
+ int OnInit() override {
+ int return_code = chromeos::DBusDaemon::OnInit();
+ if (return_code != EX_OK)
+ return return_code;
+
+ object_manager_.reset(new org::chromium::Buffet::ObjectManagerProxy{bus_});
manager_proxy_.reset(new org::chromium::Buffet::ManagerProxy{bus_});
- root_proxy_ = bus_->GetObjectProxy(
- kServiceName,
- dbus::ObjectPath(kRootServicePath));
- return EX_OK;
+
+ auto args = CommandLine::ForCurrentProcess()->GetArgs();
+
+ // Pop the command off of the args list.
+ std::string command = args.front();
+ args.erase(args.begin());
+
+ if (command.compare("TestMethod") == 0) {
+ if (args.empty() || CheckArgs(command, args, 1)) {
+ std::string message;
+ if (!args.empty())
+ message = args.back();
+ PostTask(&Daemon::CallTestMethod, message);
+ }
+ } else if (command.compare("StartDevice") == 0 ||
+ command.compare("sd") == 0) {
+ if (CheckArgs(command, args, 0))
+ PostTask(&Daemon::CallStartDevice);
+ } else if (command.compare("CheckDeviceRegistered") == 0 ||
+ command.compare("cr") == 0) {
+ if (CheckArgs(command, args, 0))
+ PostTask(&Daemon::CallCheckDeviceRegistered);
+ } else if (command.compare("GetDeviceInfo") == 0 ||
+ command.compare("di") == 0) {
+ if (CheckArgs(command, args, 0))
+ PostTask(&Daemon::CallGetDeviceInfo);
+ } else if (command.compare("RegisterDevice") == 0 ||
+ command.compare("rd") == 0) {
+ if (args.empty() || CheckArgs(command, args, 1)) {
+ std::string dict;
+ if (!args.empty())
+ dict = args.back();
+ PostTask(&Daemon::CallRegisterDevice, dict);
+ }
+ } else if (command.compare("UpdateState") == 0 ||
+ command.compare("us") == 0) {
+ if (CheckArgs(command, args, 2))
+ PostTask(&Daemon::CallUpdateState, args.front(), args.back());
+ } else if (command.compare("AddCommand") == 0 ||
+ command.compare("ac") == 0) {
+ if (CheckArgs(command, args, 1))
+ PostTask(&Daemon::CallAddCommand, args.back());
+ } else if (command.compare("PendingCommands") == 0 ||
+ command.compare("pc") == 0) {
+ if (CheckArgs(command, args, 0))
+ // CallGetPendingCommands relies on ObjectManager but it is being
+ // initialized asynchronously without a way to get a callback when
+ // it is ready to be used. So, just wait a bit before calling its
+ // methods.
+ PostDelayedTask(&Daemon::CallGetPendingCommands,
+ base::TimeDelta::FromMilliseconds(100));
+ } else {
+ fprintf(stderr, "Unknown command: '%s'\n", command.c_str());
+ usage();
+ Quit();
+ return EX_USAGE;
+ }
+ return EX_OK;
}
- int CallTestMethod(const CommandLine::StringVector& args) {
- std::string message;
- if (!args.empty())
- message = args.front();
+ void OnShutdown(int* return_code) override {
+ if (*return_code == EX_OK)
+ *return_code = exit_code_;
+ }
+ private:
+ void ReportError(Error* error) {
+ fprintf(stderr, "Failed to receive a response: %s\n",
+ error->GetMessage().c_str());
+ exit_code_ = EX_UNAVAILABLE;
+ Quit();
+ }
+
+ bool CheckArgs(const std::string& command,
+ const std::vector<std::string>& args,
+ size_t expected_arg_count) {
+ if (args.size() == expected_arg_count)
+ return true;
+ fprintf(stderr, "Invalid number of arguments for command '%s'\n",
+ command.c_str());
+ usage();
+ exit_code_ = EX_USAGE;
+ Quit();
+ return false;
+ }
+
+ template<typename... Args>
+ void PostTask(void (Daemon::*fn)(const Args&...), const Args&... args) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(fn, base::Unretained(this), args...));
+ }
+
+ template<typename... Args>
+ void PostDelayedTask(void (Daemon::*fn)(const Args&...),
+ const base::TimeDelta& delay,
+ const Args&... args) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, base::Bind(fn, base::Unretained(this), args...), delay);
+ }
+
+ void CallTestMethod(const std::string& message) {
ErrorPtr error;
std::string response_message;
if (!manager_proxy_->TestMethod(message, &response_message, &error)) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
+ return ReportError(error.get());
}
-
- std::cout << "Received a response: " << response_message << std::endl;
- return EX_OK;
+ printf("Received a response: %s\n", response_message.c_str());
+ Quit();
}
- int CallManagerStartDevice(const CommandLine::StringVector& args) {
- if (!args.empty()) {
- std::cerr << "Invalid number of arguments for "
- << "Manager." << kManagerStartDevice << std::endl;
- usage();
- return EX_USAGE;
- }
-
+ void CallStartDevice() {
ErrorPtr error;
if (!manager_proxy_->StartDevice(&error)) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
+ return ReportError(error.get());
}
-
- return EX_OK;
+ Quit();
}
- int CallManagerCheckDeviceRegistered(const CommandLine::StringVector& args) {
- if (!args.empty()) {
- std::cerr << "Invalid number of arguments for "
- << "Manager." << kManagerCheckDeviceRegistered << std::endl;
- usage();
- return EX_USAGE;
- }
-
+ void CallCheckDeviceRegistered() {
ErrorPtr error;
std::string device_id;
if (!manager_proxy_->CheckDeviceRegistered(&device_id, &error)) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
+ return ReportError(error.get());
}
- std::cout << "Device ID: "
- << (device_id.empty() ? std::string("<unregistered>") : device_id)
- << std::endl;
- return EX_OK;
+ printf("Device ID: %s\n",
+ device_id.empty() ? "<unregistered>" : device_id.c_str());
+ Quit();
}
- int CallManagerGetDeviceInfo(const CommandLine::StringVector& args) {
- if (!args.empty()) {
- std::cerr << "Invalid number of arguments for "
- << "Manager." << kManagerGetDeviceInfo << std::endl;
- usage();
- return EX_USAGE;
- }
-
+ void CallGetDeviceInfo() {
ErrorPtr error;
std::string device_info;
if (!manager_proxy_->GetDeviceInfo(&device_info, &error)) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
+ return ReportError(error.get());
}
- std::cout << "Device Info: "
- << (device_info.empty() ? std::string("<unregistered>") : device_info)
- << std::endl;
- return EX_OK;
+ printf("Device Info: %s\n",
+ device_info.empty() ? "<unregistered>" : device_info.c_str());
+ Quit();
}
- int CallManagerRegisterDevice(const CommandLine::StringVector& args) {
- if (args.size() > 1) {
- std::cerr << "Invalid number of arguments for "
- << "Manager." << kManagerRegisterDevice << std::endl;
- usage();
- return EX_USAGE;
- }
-
- VariantDictionary params;
+ void CallRegisterDevice(const std::string& args) {
+ chromeos::VariantDictionary params;
if (!args.empty()) {
- auto key_values = chromeos::data_encoding::WebParamsDecode(args.front());
+ auto key_values = chromeos::data_encoding::WebParamsDecode(args);
for (const auto& pair : key_values) {
params.insert(std::make_pair(pair.first, chromeos::Any(pair.second)));
}
@@ -163,79 +210,50 @@
ErrorPtr error;
std::string device_id;
if (!manager_proxy_->RegisterDevice(params, &device_id, &error)) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
+ return ReportError(error.get());
}
- std::cout << "Device registered: " << device_id << std::endl;
- return EX_OK;
+ printf("Device registered: %s\n", device_id.c_str());
+ Quit();
}
- int CallManagerUpdateState(const CommandLine::StringVector& args) {
- if (args.size() != 2) {
- std::cerr << "Invalid number of arguments for "
- << "Manager." << kManagerUpdateStateMethod << std::endl;
- usage();
- return EX_USAGE;
- }
-
+ void CallUpdateState(const std::string& prop, const std::string& value) {
ErrorPtr error;
- VariantDictionary property_set{{args.front(), args.back()}};
+ chromeos::VariantDictionary property_set{{prop, value}};
if (!manager_proxy_->UpdateState(property_set, &error)) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
+ return ReportError(error.get());
}
- return EX_OK;
+ Quit();
}
- int CallManagerAddCommand(const CommandLine::StringVector& args) {
- if (args.size() != 1) {
- std::cerr << "Invalid number of arguments for "
- << "Manager." << kManagerAddCommand << std::endl;
- usage();
- return EX_USAGE;
- }
-
+ void CallAddCommand(const std::string& command) {
ErrorPtr error;
- if (!manager_proxy_->AddCommand(args.front(), &error)) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
+ if (!manager_proxy_->AddCommand(command, &error)) {
+ return ReportError(error.get());
}
- return EX_OK;
+ Quit();
}
- int CallRootGetManagedObjects(const CommandLine::StringVector& args) {
- if (!args.empty()) {
- std::cerr << "Invalid number of arguments for "
- << dbus::kObjectManagerGetManagedObjects << std::endl;
- usage();
- return EX_USAGE;
+ void CallGetPendingCommands() {
+ printf("Pending commands:\n");
+ for (auto* cmd : object_manager_->GetCommandInstances()) {
+ printf("%10s (%-3d) - '%s' (id:%s)\n",
+ cmd->status().c_str(),
+ cmd->progress(),
+ cmd->name().c_str(),
+ cmd->id().c_str());
}
-
- ErrorPtr error;
- auto response = CallMethodAndBlock(
- root_proxy_,
- dbus::kObjectManagerInterface, dbus::kObjectManagerGetManagedObjects,
- &error);
- if (!response) {
- std::cout << "Failed to receive a response:"
- << error->GetMessage() << std::endl;
- return EX_UNAVAILABLE;
- }
- std::cout << response->ToString() << std::endl;
- return EX_OK;
+ Quit();
}
- private:
- scoped_refptr<dbus::Bus> bus_;
+ std::unique_ptr<org::chromium::Buffet::ObjectManagerProxy> object_manager_;
std::unique_ptr<org::chromium::Buffet::ManagerProxy> manager_proxy_;
- dbus::ObjectProxy* root_proxy_{nullptr};
+ int exit_code_ = EX_OK;
+
+ DISALLOW_COPY_AND_ASSIGN(Daemon);
};
-} // namespace
+} // anonymous namespace
int main(int argc, char** argv) {
CommandLine::Init(argc, argv);
@@ -246,48 +264,6 @@
return EX_USAGE;
}
- // Pop the command off of the args list.
- std::string command = args.front();
- args.erase(args.begin());
- int err = EX_USAGE;
- BuffetHelperProxy helper;
- err = helper.Init();
- if (err) {
- std::cerr << "Error initializing proxies." << std::endl;
- return err;
- }
-
- if (command.compare(kManagerTestMethod) == 0) {
- err = helper.CallTestMethod(args);
- } else if (command.compare(kManagerStartDevice) == 0 ||
- command.compare("sd") == 0) {
- err = helper.CallManagerStartDevice(args);
- } else if (command.compare(kManagerCheckDeviceRegistered) == 0 ||
- command.compare("cr") == 0) {
- err = helper.CallManagerCheckDeviceRegistered(args);
- } else if (command.compare(kManagerGetDeviceInfo) == 0 ||
- command.compare("di") == 0) {
- err = helper.CallManagerGetDeviceInfo(args);
- } else if (command.compare(kManagerRegisterDevice) == 0 ||
- command.compare("rd") == 0) {
- err = helper.CallManagerRegisterDevice(args);
- } else if (command.compare(kManagerUpdateStateMethod) == 0 ||
- command.compare("us") == 0) {
- err = helper.CallManagerUpdateState(args);
- } else if (command.compare(kManagerAddCommand) == 0 ||
- command.compare("ac") == 0) {
- err = helper.CallManagerAddCommand(args);
- } else if (command.compare(dbus::kObjectManagerGetManagedObjects) == 0) {
- err = helper.CallRootGetManagedObjects(args);
- } else {
- std::cerr << "Unknown command: " << command << std::endl;
- usage();
- }
-
- if (err) {
- std::cerr << "Done, with errors." << std::endl;
- } else {
- std::cout << "Done." << std::endl;
- }
- return err;
+ Daemon daemon;
+ return daemon.Run();
}