libweave: Extract platform independent part of PeerdClient The rest of PeerdClinet will be moved into buffet. BUG=brillo:1267 TEST='FEATURES=test emerge-gizmo buffet' Change-Id: I884cfe377334f8d3fced5a493de8d407bb6bd3ca Reviewed-on: https://chromium-review.googlesource.com/289945 Reviewed-by: Alex Vakulenko <avakulenko@chromium.org> Commit-Queue: Vitaly Buka <vitalybuka@chromium.org> Trybot-Ready: Vitaly Buka <vitalybuka@chromium.org> Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp index 8d22323..a679314 100644 --- a/buffet/buffet.gyp +++ b/buffet/buffet.gyp
@@ -64,6 +64,7 @@ '../libweave/src/privet/privet_handler.cc', '../libweave/src/privet/privet_manager.cc', '../libweave/src/privet/privet_types.cc', + '../libweave/src/privet/publisher.cc', '../libweave/src/privet/security_manager.cc', '../libweave/src/privet/shill_client.cc', '../libweave/src/privet/privet_types.cc',
diff --git a/libweave/include/weave/mdns.h b/libweave/include/weave/mdns.h new file mode 100644 index 0000000..d1b7232 --- /dev/null +++ b/libweave/include/weave/mdns.h
@@ -0,0 +1,36 @@ +// Copyright 2015 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 LIBWEAVE_INCLUDE_WEAVE_MDNS_H_ +#define LIBWEAVE_INCLUDE_WEAVE_MDNS_H_ + +#include <map> +#include <string> + +#include <base/callback.h> + +namespace weave { + +class Mdns { + public: + // Publishes new service on mDns or updates existing one. + virtual void PublishService( + const std::string& service_name, + uint16_t port, + const std::map<std::string, std::string>& txt) = 0; + + // Stops publishing service. + virtual void StopPublishing(const std::string& service_name) = 0; + + // Returns permanent device ID. + // TODO(vitalybuka): Find better place for this information. + virtual std::string GetId() const = 0; + + protected: + virtual ~Mdns() = default; +}; + +} // namespace weave + +#endif // LIBWEAVE_INCLUDE_WEAVE_MDNS_H_
diff --git a/libweave/src/privet/peerd_client.cc b/libweave/src/privet/peerd_client.cc index d37740e..1ed7796 100644 --- a/libweave/src/privet/peerd_client.cc +++ b/libweave/src/privet/peerd_client.cc
@@ -10,12 +10,6 @@ #include <chromeos/errors/error.h> #include <chromeos/strings/string_utils.h> -#include "libweave/src/privet/cloud_delegate.h" -#include "libweave/src/privet/device_delegate.h" -#include "libweave/src/privet/wifi_bootstrap_manager.h" -#include "libweave/src/privet/wifi_ssid_generator.h" - -using chromeos::string_utils::Join; using org::chromium::peerd::PeerProxy; namespace weave { @@ -28,8 +22,6 @@ // updates relevant for a short amount of time. const int kCommitTimeoutSeconds = 1; -// The name of the service we'll expose via peerd. -const char kPrivetServiceId[] = "privet"; const char kSelfPath[] = "/org/chromium/peerd/Self"; void OnError(const std::string& operation, chromeos::Error* error) { @@ -38,16 +30,8 @@ } // namespace -PeerdClient::PeerdClient(const scoped_refptr<dbus::Bus>& bus, - const DeviceDelegate* device, - const CloudDelegate* cloud, - const WifiDelegate* wifi) - : peerd_object_manager_proxy_{bus}, - device_{device}, - cloud_{cloud}, - wifi_{wifi} { - CHECK(device_); - CHECK(cloud_); +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( @@ -64,6 +48,28 @@ 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(); @@ -110,44 +116,16 @@ // Do nothing if peerd hasn't started yet. if (peerd_manager_proxy_ == nullptr) return; - - std::string name; - std::string model_id; - if (!cloud_->GetName(&name, nullptr) || - !cloud_->GetModelId(&model_id, nullptr)) { - return; - } - DCHECK_EQ(model_id.size(), 5U); - VLOG(1) << "Starting peerd advertising."; - const uint16_t port = device_->GetHttpEnpoint().first; + CHECK_NE(port_, 0); + CHECK(!service_name_.empty()); + CHECK(!txt_.empty()); std::map<std::string, chromeos::Any> mdns_options{ - {"port", chromeos::Any{port}}, + {"port", chromeos::Any{port_}}, }; - DCHECK_NE(port, 0); - - std::string services; - if (!cloud_->GetServices().empty()) - services += "_"; - services += Join(",_", cloud_->GetServices()); - - std::map<std::string, std::string> txt_record{ - {"txtvers", "3"}, - {"ty", name}, - {"services", services}, - {"id", GetId()}, - {"mmid", model_id}, - {"flags", WifiSsidGenerator{cloud_, wifi_}.GenerateFlags()}, - }; - - if (!cloud_->GetCloudId().empty()) - txt_record.emplace("gcd_id", cloud_->GetCloudId()); - - if (!cloud_->GetDescription().empty()) - txt_record.emplace("note", cloud_->GetDescription()); peerd_manager_proxy_->ExposeServiceAsync( - kPrivetServiceId, txt_record, {{"mdns", mdns_options}}, base::Closure(), + service_name_, txt_, {{"mdns", mdns_options}}, base::Closure(), base::Bind(&OnError, "ExposeService")); } @@ -156,12 +134,14 @@ return; VLOG(1) << "Stopping peerd advertising."; - peerd_manager_proxy_->RemoveExposedServiceAsync( - kPrivetServiceId, base::Closure(), base::Bind(&OnError, "RemoveService")); + if (!service_name_.empty()) { + peerd_manager_proxy_->RemoveExposedServiceAsync( + service_name_, base::Closure(), base::Bind(&OnError, "RemoveService")); + } } void PeerdClient::UpdateImpl() { - if (device_->GetHttpEnpoint().first == 0) + if (port_ == 0) return RemoveService(); ExposeService(); }
diff --git a/libweave/src/privet/peerd_client.h b/libweave/src/privet/peerd_client.h index b75e253..de90248 100644 --- a/libweave/src/privet/peerd_client.h +++ b/libweave/src/privet/peerd_client.h
@@ -5,14 +5,15 @@ #ifndef LIBWEAVE_SRC_PRIVET_PEERD_CLIENT_H_ #define LIBWEAVE_SRC_PRIVET_PEERD_CLIENT_H_ +#include <map> #include <memory> #include <string> #include <base/callback.h> #include <base/memory/ref_counted.h> -#include "libweave/src/privet/identity_delegate.h" #include "peerd/dbus-proxies.h" +#include "weave/mdns.h" namespace dbus { class Bus; @@ -21,26 +22,19 @@ namespace weave { namespace privet { -class CloudDelegate; -class DeviceDelegate; -class WifiDelegate; - -// Publishes prived service on mDns using peerd. -class PeerdClient : public IdentityDelegate { +// Publishes privet service on mDns using peerd. +class PeerdClient : public Mdns { public: - PeerdClient(const scoped_refptr<dbus::Bus>& bus, - const DeviceDelegate* device, - const CloudDelegate* cloud, - const WifiDelegate* wifi); - ~PeerdClient(); + explicit PeerdClient(const scoped_refptr<dbus::Bus>& bus); + ~PeerdClient() override; - // Get the unique identifier for this device. Note that if peerd has - // never been seen, this may be the empty string. + // 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; - // Updates published information. Removes service if HTTP is not alive. - void Update(); - private: void OnPeerdOnline(org::chromium::peerd::ManagerProxy* manager_proxy); void OnPeerdOffline(const dbus::ObjectPath& object_path); @@ -48,6 +42,9 @@ 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(); @@ -57,15 +54,17 @@ // |peerd_manager_proxy_| is owned by |peerd_object_manager_proxy_|. org::chromium::peerd::ManagerProxy* peerd_manager_proxy_{nullptr}; - const DeviceDelegate* device_{nullptr}; - const CloudDelegate* cloud_{nullptr}; - const WifiDelegate* wifi_{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 privet
diff --git a/libweave/src/privet/privet_manager.cc b/libweave/src/privet/privet_manager.cc index 698283a..b65ba06 100644 --- a/libweave/src/privet/privet_manager.cc +++ b/libweave/src/privet/privet_manager.cc
@@ -35,6 +35,7 @@ #include "libweave/src/privet/device_delegate.h" #include "libweave/src/privet/peerd_client.h" #include "libweave/src/privet/privet_handler.h" +#include "libweave/src/privet/publisher.h" #include "libweave/src/privet/shill_client.h" namespace weave { @@ -88,12 +89,15 @@ wifi_bootstrap_manager_->Init(); } - peerd_client_.reset(new PeerdClient(bus, device_.get(), cloud_.get(), - wifi_bootstrap_manager_.get())); + peerd_client_.reset(new PeerdClient(bus)); + + publisher_.reset(new Publisher(device_.get(), cloud_.get(), + wifi_bootstrap_manager_.get(), + peerd_client_.get())); privet_handler_.reset( new PrivetHandler(cloud_.get(), device_.get(), security_.get(), - wifi_bootstrap_manager_.get(), peerd_client_.get())); + wifi_bootstrap_manager_.get(), publisher_.get())); web_server_.reset(new libwebserv::Server); web_server_->OnProtocolHandlerConnected(base::Bind( @@ -195,8 +199,8 @@ } void Manager::OnChanged() { - if (peerd_client_) - peerd_client_->Update(); + if (publisher_) + publisher_->Update(); } void Manager::OnConnectivityChanged(bool online) { @@ -206,8 +210,8 @@ void Manager::OnProtocolHandlerConnected(ProtocolHandler* protocol_handler) { if (protocol_handler->GetName() == ProtocolHandler::kHttp) { device_->SetHttpPort(*protocol_handler->GetPorts().begin()); - if (peerd_client_) - peerd_client_->Update(); + if (publisher_) + publisher_->Update(); } else if (protocol_handler->GetName() == ProtocolHandler::kHttps) { device_->SetHttpsPort(*protocol_handler->GetPorts().begin()); security_->SetCertificateFingerprint( @@ -218,8 +222,8 @@ void Manager::OnProtocolHandlerDisconnected(ProtocolHandler* protocol_handler) { if (protocol_handler->GetName() == ProtocolHandler::kHttp) { device_->SetHttpPort(0); - if (peerd_client_) - peerd_client_->Update(); + if (publisher_) + publisher_->Update(); } else if (protocol_handler->GetName() == ProtocolHandler::kHttps) { device_->SetHttpsPort(0); security_->SetCertificateFingerprint({});
diff --git a/libweave/src/privet/privet_manager.h b/libweave/src/privet/privet_manager.h index 9ec3984..cb77b12 100644 --- a/libweave/src/privet/privet_manager.h +++ b/libweave/src/privet/privet_manager.h
@@ -35,6 +35,7 @@ class CommandManager; class DeviceRegistrationInfo; +class Mdns; class StateManager; namespace privet { @@ -45,6 +46,7 @@ class DeviceDelegate; class PeerdClient; class PrivetHandler; +class Publisher; class SecurityManager; class ShillClient; @@ -102,6 +104,7 @@ std::unique_ptr<ApManagerClient> ap_manager_client_; std::unique_ptr<WifiBootstrapManager> wifi_bootstrap_manager_; std::unique_ptr<PeerdClient> peerd_client_; + std::unique_ptr<Publisher> publisher_; std::unique_ptr<PrivetHandler> privet_handler_; std::unique_ptr<libwebserv::Server> web_server_;
diff --git a/libweave/src/privet/publisher.cc b/libweave/src/privet/publisher.cc new file mode 100644 index 0000000..877aa02 --- /dev/null +++ b/libweave/src/privet/publisher.cc
@@ -0,0 +1,96 @@ +// Copyright 2015 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 "libweave/src/privet/publisher.h" + +#include <map> + +#include <chromeos/errors/error.h> +#include <chromeos/strings/string_utils.h> + +#include "libweave/src/privet/cloud_delegate.h" +#include "libweave/src/privet/device_delegate.h" +#include "libweave/src/privet/wifi_bootstrap_manager.h" +#include "libweave/src/privet/wifi_ssid_generator.h" +#include "weave/mdns.h" + +using chromeos::string_utils::Join; + +namespace weave { +namespace privet { + +namespace { + +// The name of the service we'll expose via peerd. +const char kPrivetServiceId[] = "privet"; + +} // namespace + +Publisher::Publisher(const DeviceDelegate* device, + const CloudDelegate* cloud, + const WifiDelegate* wifi, + Mdns* mdns) + : mdns_{mdns}, device_{device}, cloud_{cloud}, wifi_{wifi} { + CHECK(device_); + CHECK(cloud_); + CHECK(mdns_); +} + +Publisher::~Publisher() { + RemoveService(); +} + +std::string Publisher::GetId() const { + return mdns_->GetId(); +} + +void Publisher::Update() { + if (device_->GetHttpEnpoint().first == 0) + return RemoveService(); + ExposeService(); +} + +void Publisher::ExposeService() { + std::string name; + std::string model_id; + if (!cloud_->GetName(&name, nullptr) || + !cloud_->GetModelId(&model_id, nullptr)) { + return; + } + DCHECK_EQ(model_id.size(), 5U); + + VLOG(1) << "Starting peerd advertising."; + const uint16_t port = device_->GetHttpEnpoint().first; + DCHECK_NE(port, 0); + + std::string services; + if (!cloud_->GetServices().empty()) + services += "_"; + services += Join(",_", cloud_->GetServices()); + + std::map<std::string, std::string> txt_record{ + {"txtvers", "3"}, + {"ty", name}, + {"services", services}, + {"id", GetId()}, + {"mmid", model_id}, + {"flags", WifiSsidGenerator{cloud_, wifi_}.GenerateFlags()}, + }; + + if (!cloud_->GetCloudId().empty()) + txt_record.emplace("gcd_id", cloud_->GetCloudId()); + + if (!cloud_->GetDescription().empty()) + txt_record.emplace("note", cloud_->GetDescription()); + + mdns_->PublishService(kPrivetServiceId, port, txt_record); +} + +void Publisher::RemoveService() { + VLOG(1) << "Stopping service publishing."; + mdns_->StopPublishing(kPrivetServiceId); +} + +} // namespace privet +} // namespace weave
diff --git a/libweave/src/privet/publisher.h b/libweave/src/privet/publisher.h new file mode 100644 index 0000000..1655ae1 --- /dev/null +++ b/libweave/src/privet/publisher.h
@@ -0,0 +1,60 @@ +// Copyright 2015 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 LIBWEAVE_SRC_PRIVET_PUBLISHER_H_ +#define LIBWEAVE_SRC_PRIVET_PUBLISHER_H_ + +#include <memory> +#include <string> + +#include <base/macros.h> + +#include "libweave/src/privet/identity_delegate.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace weave { + +class Mdns; + +namespace privet { + +class CloudDelegate; +class DeviceDelegate; +class WifiDelegate; + +// Publishes privet service on mDns. +class Publisher : public IdentityDelegate { + public: + Publisher(const DeviceDelegate* device, + const CloudDelegate* cloud, + const WifiDelegate* wifi, + Mdns* mdns); + ~Publisher() override; + + // IdentityDelegate implementation. + std::string GetId() const override; + + // Updates published information. Removes service if HTTP is not alive. + void Update(); + + private: + void ExposeService(); + void RemoveService(); + + Mdns* mdns_{nullptr}; + + const DeviceDelegate* device_{nullptr}; + const CloudDelegate* cloud_{nullptr}; + const WifiDelegate* wifi_{nullptr}; + + DISALLOW_COPY_AND_ASSIGN(Publisher); +}; + +} // namespace privet +} // namespace weave + +#endif // LIBWEAVE_SRC_PRIVET_PUBLISHER_H_