buffet: Move platform dependent part of PeerdClient out of libweave
Peerd is brillo specific service.
BUG=brillo:1267
TEST='FEATURES=test emerge-gizmo buffet'
Change-Id: I666da7ba0ed6a6c55472fed8c5f5beb16b562619
Reviewed-on: https://chromium-review.googlesource.com/289914
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/buffet.gyp b/buffet/buffet.gyp
index a679314..3c59e0a 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -32,6 +32,7 @@
'dbus_conversion.cc',
'dbus_constants.cc',
'manager.cc',
+ 'peerd_client.cc',
'../libweave/src/base_api_handler.cc',
'../libweave/src/buffet_config.cc',
'../libweave/src/commands/cloud_command_proxy.cc',
@@ -60,7 +61,6 @@
'../libweave/src/privet/constants.cc',
'../libweave/src/privet/device_delegate.cc',
'../libweave/src/privet/openssl_utils.cc',
- '../libweave/src/privet/peerd_client.cc',
'../libweave/src/privet/privet_handler.cc',
'../libweave/src/privet/privet_manager.cc',
'../libweave/src/privet/privet_types.cc',
diff --git a/buffet/manager.cc b/buffet/manager.cc
index 85c61c1..f6b27a3 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -25,6 +25,7 @@
#include "buffet/dbus_command_dispatcher.h"
#include "buffet/dbus_conversion.h"
+#include "buffet/peerd_client.h"
#include "weave/enum_to_string.h"
using chromeos::dbus_utils::AsyncEventSequencer;
@@ -54,8 +55,10 @@
void Manager::Start(const weave::Device::Options& options,
AsyncEventSequencer* sequencer) {
+ peerd_client_.reset(new PeerdClient{dbus_object_.GetBus()});
+
device_ = weave::Device::Create();
- device_->Start(options, &dbus_object_, sequencer);
+ device_->Start(options, peerd_client_.get(), &dbus_object_, sequencer);
command_dispatcher_.reset(new DBusCommandDispacher{
dbus_object_.GetObjectManager(), device_->GetCommands()});
diff --git a/buffet/manager.h b/buffet/manager.h
index 9dc84d8..e9fcad9 100644
--- a/buffet/manager.h
+++ b/buffet/manager.h
@@ -30,6 +30,8 @@
namespace buffet {
+class PeerdClient;
+
class DBusCommandDispacher;
template<typename... Types>
@@ -114,6 +116,7 @@
org::chromium::Buffet::ManagerAdaptor dbus_adaptor_{this};
chromeos::dbus_utils::DBusObject dbus_object_;
+ std::unique_ptr<PeerdClient> peerd_client_;
std::unique_ptr<weave::Device> device_;
std::unique_ptr<DBusCommandDispacher> command_dispatcher_;
diff --git a/buffet/peerd_client.cc b/buffet/peerd_client.cc
new file mode 100644
index 0000000..cfbf64a
--- /dev/null
+++ b/buffet/peerd_client.cc
@@ -0,0 +1,148 @@
+// Copyright 2014 The Chromium OS 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 "buffet/peerd_client.h"
+
+#include <map>
+
+#include <base/message_loop/message_loop.h>
+#include <chromeos/errors/error.h>
+#include <chromeos/strings/string_utils.h>
+
+using org::chromium::peerd::PeerProxy;
+
+namespace buffet {
+
+namespace {
+
+// Commit changes only if no update request happened during the timeout.
+// Usually updates happen in batches, so we don't want to flood network with
+// updates relevant for a short amount of time.
+const int kCommitTimeoutSeconds = 1;
+
+const char kSelfPath[] = "/org/chromium/peerd/Self";
+
+void OnError(const std::string& operation, chromeos::Error* error) {
+ LOG(ERROR) << operation << " failed:" << error->GetMessage();
+}
+
+} // namespace
+
+PeerdClient::PeerdClient(const scoped_refptr<dbus::Bus>& bus)
+ : peerd_object_manager_proxy_{bus} {
+ peerd_object_manager_proxy_.SetManagerAddedCallback(
+ base::Bind(&PeerdClient::OnPeerdOnline, weak_ptr_factory_.GetWeakPtr()));
+ peerd_object_manager_proxy_.SetManagerRemovedCallback(
+ base::Bind(&PeerdClient::OnPeerdOffline, weak_ptr_factory_.GetWeakPtr()));
+ peerd_object_manager_proxy_.SetPeerAddedCallback(
+ base::Bind(&PeerdClient::OnNewPeer, weak_ptr_factory_.GetWeakPtr()));
+}
+
+PeerdClient::~PeerdClient() {
+ RemoveService();
+}
+
+std::string PeerdClient::GetId() const {
+ return device_id_;
+}
+
+void PeerdClient::PublishService(
+ const std::string& service_name,
+ uint16_t port,
+ const std::map<std::string, std::string>& txt) {
+ // Only one service supported.
+ CHECK(service_name_.empty() || service_name_ == service_name);
+ service_name_ = service_name;
+ port_ = port;
+ txt_ = txt;
+
+ Update();
+}
+
+void PeerdClient::StopPublishing(const std::string& service_name) {
+ // Only one service supported.
+ CHECK(service_name_.empty() || service_name_ == service_name);
+ service_name_ = service_name;
+ port_ = 0;
+
+ Update();
+}
+
+void PeerdClient::Update() {
+ // Abort pending updates, and wait for more changes.
+ restart_weak_ptr_factory_.InvalidateWeakPtrs();
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, base::Bind(&PeerdClient::UpdateImpl,
+ restart_weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(kCommitTimeoutSeconds));
+}
+
+void PeerdClient::OnNewPeer(PeerProxy* peer) {
+ if (!peer || peer->GetObjectPath().value() != kSelfPath)
+ return;
+ peer->SetPropertyChangedCallback(base::Bind(
+ &PeerdClient::OnPeerPropertyChanged, weak_ptr_factory_.GetWeakPtr()));
+ OnPeerPropertyChanged(peer, PeerProxy::UUIDName());
+}
+
+void PeerdClient::OnPeerPropertyChanged(PeerProxy* peer,
+ const std::string& property_name) {
+ if (property_name != PeerProxy::UUIDName() ||
+ peer->GetObjectPath().value() != kSelfPath)
+ return;
+ const std::string new_id{peer->uuid()};
+ if (new_id != device_id_) {
+ device_id_ = new_id;
+ Update();
+ }
+}
+
+void PeerdClient::OnPeerdOnline(
+ org::chromium::peerd::ManagerProxy* manager_proxy) {
+ peerd_manager_proxy_ = manager_proxy;
+ VLOG(1) << "Peerd manager is online at '"
+ << manager_proxy->GetObjectPath().value() << "'.";
+ Update();
+}
+
+void PeerdClient::OnPeerdOffline(const dbus::ObjectPath& object_path) {
+ peerd_manager_proxy_ = nullptr;
+ VLOG(1) << "Peerd manager is now offline.";
+}
+
+void PeerdClient::ExposeService() {
+ // Do nothing if peerd hasn't started yet.
+ if (peerd_manager_proxy_ == nullptr)
+ return;
+ VLOG(1) << "Starting peerd advertising.";
+ CHECK_NE(port_, 0);
+ CHECK(!service_name_.empty());
+ CHECK(!txt_.empty());
+ std::map<std::string, chromeos::Any> mdns_options{
+ {"port", chromeos::Any{port_}},
+ };
+
+ peerd_manager_proxy_->ExposeServiceAsync(
+ service_name_, txt_, {{"mdns", mdns_options}}, base::Closure(),
+ base::Bind(&OnError, "ExposeService"));
+}
+
+void PeerdClient::RemoveService() {
+ if (peerd_manager_proxy_ == nullptr)
+ return;
+
+ VLOG(1) << "Stopping peerd advertising.";
+ if (!service_name_.empty()) {
+ peerd_manager_proxy_->RemoveExposedServiceAsync(
+ service_name_, base::Closure(), base::Bind(&OnError, "RemoveService"));
+ }
+}
+
+void PeerdClient::UpdateImpl() {
+ if (port_ == 0)
+ return RemoveService();
+ ExposeService();
+}
+
+} // namespace buffet
diff --git a/buffet/peerd_client.h b/buffet/peerd_client.h
new file mode 100644
index 0000000..e24cd32
--- /dev/null
+++ b/buffet/peerd_client.h
@@ -0,0 +1,71 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BUFFET_PRIVET_PEERD_CLIENT_H_
+#define BUFFET_PRIVET_PEERD_CLIENT_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <base/callback.h>
+#include <base/memory/ref_counted.h>
+
+#include "peerd/dbus-proxies.h"
+#include "weave/mdns.h"
+
+namespace dbus {
+class Bus;
+} // namespace dbus
+
+namespace buffet {
+
+// Publishes privet service on mDns using peerd.
+class PeerdClient : public weave::Mdns {
+ public:
+ explicit PeerdClient(const scoped_refptr<dbus::Bus>& bus);
+ ~PeerdClient() override;
+
+ // Mdns implementation.
+ void PublishService(const std::string& service_name,
+ uint16_t port,
+ const std::map<std::string, std::string>& txt) override;
+ void StopPublishing(const std::string& service_name) override;
+ std::string GetId() const override;
+
+ private:
+ void OnPeerdOnline(org::chromium::peerd::ManagerProxy* manager_proxy);
+ void OnPeerdOffline(const dbus::ObjectPath& object_path);
+ void OnNewPeer(org::chromium::peerd::PeerProxy* peer_proxy);
+ void OnPeerPropertyChanged(org::chromium::peerd::PeerProxy* peer_proxy,
+ const std::string& property_name);
+
+ // Updates published information. Removes service if HTTP is not alive.
+ void Update();
+
+ void ExposeService();
+ void RemoveService();
+
+ void UpdateImpl();
+
+ org::chromium::peerd::ObjectManagerProxy peerd_object_manager_proxy_;
+ // |peerd_manager_proxy_| is owned by |peerd_object_manager_proxy_|.
+ org::chromium::peerd::ManagerProxy* peerd_manager_proxy_{nullptr};
+
+ // Cached value of the device ID that we got from peerd.
+ std::string device_id_;
+
+ std::string service_name_;
+ uint16_t port_{0};
+ std::map<std::string, std::string> txt_;
+
+ base::WeakPtrFactory<PeerdClient> restart_weak_ptr_factory_{this};
+ base::WeakPtrFactory<PeerdClient> weak_ptr_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(PeerdClient);
+};
+
+} // namespace buffet
+
+#endif // BUFFET_PRIVET_PEERD_CLIENT_H_