blob: 67847bd854a03efc79f583fa390e4ab8070129c7 [file] [log] [blame]
Vitaly Buka7042c582015-07-30 17:02:14 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "buffet/peerd_client.h"
6
7#include <map>
Alex Vakulenkoe32375b2015-09-28 08:55:40 -07008#include <vector>
Vitaly Buka7042c582015-07-30 17:02:14 -07009
10#include <base/message_loop/message_loop.h>
Alex Vakulenko41705852015-10-13 10:12:06 -070011#include <brillo/errors/error.h>
12#include <brillo/strings/string_utils.h>
Vitaly Buka7042c582015-07-30 17:02:14 -070013
14using org::chromium::peerd::PeerProxy;
15
16namespace buffet {
17
18namespace {
19
20// Commit changes only if no update request happened during the timeout.
21// Usually updates happen in batches, so we don't want to flood network with
22// updates relevant for a short amount of time.
23const int kCommitTimeoutSeconds = 1;
24
Alex Vakulenko41705852015-10-13 10:12:06 -070025void OnError(const std::string& operation, brillo::Error* error) {
Vitaly Buka7042c582015-07-30 17:02:14 -070026 LOG(ERROR) << operation << " failed:" << error->GetMessage();
27}
28
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070029const char kExpectedServiceType[] = "_privet._tcp";
30const char kServiceName[] = "privet";
31
Vitaly Buka7042c582015-07-30 17:02:14 -070032} // namespace
33
34PeerdClient::PeerdClient(const scoped_refptr<dbus::Bus>& bus)
35 : peerd_object_manager_proxy_{bus} {
36 peerd_object_manager_proxy_.SetManagerAddedCallback(
37 base::Bind(&PeerdClient::OnPeerdOnline, weak_ptr_factory_.GetWeakPtr()));
38 peerd_object_manager_proxy_.SetManagerRemovedCallback(
39 base::Bind(&PeerdClient::OnPeerdOffline, weak_ptr_factory_.GetWeakPtr()));
Vitaly Buka7042c582015-07-30 17:02:14 -070040}
41
42PeerdClient::~PeerdClient() {
43 RemoveService();
44}
45
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070046void PeerdClient::PublishService(const std::string& service_type,
47 uint16_t port,
48 const std::vector<std::string>& txt) {
Vitaly Buka7042c582015-07-30 17:02:14 -070049 // Only one service supported.
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070050 CHECK_EQ(service_type, kExpectedServiceType);
Vitaly Buka7042c582015-07-30 17:02:14 -070051 port_ = port;
52 txt_ = txt;
Vitaly Buka7042c582015-07-30 17:02:14 -070053 Update();
54}
55
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070056void PeerdClient::StopPublishing(const std::string& service_type) {
Vitaly Buka7042c582015-07-30 17:02:14 -070057 // Only one service supported.
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070058 CHECK_EQ(service_type, kExpectedServiceType);
Vitaly Buka7042c582015-07-30 17:02:14 -070059 port_ = 0;
Vitaly Buka7042c582015-07-30 17:02:14 -070060 Update();
61}
62
63void PeerdClient::Update() {
64 // Abort pending updates, and wait for more changes.
65 restart_weak_ptr_factory_.InvalidateWeakPtrs();
66 base::MessageLoop::current()->PostDelayedTask(
67 FROM_HERE, base::Bind(&PeerdClient::UpdateImpl,
68 restart_weak_ptr_factory_.GetWeakPtr()),
69 base::TimeDelta::FromSeconds(kCommitTimeoutSeconds));
70}
71
Vitaly Buka7042c582015-07-30 17:02:14 -070072void PeerdClient::OnPeerdOnline(
73 org::chromium::peerd::ManagerProxy* manager_proxy) {
74 peerd_manager_proxy_ = manager_proxy;
75 VLOG(1) << "Peerd manager is online at '"
76 << manager_proxy->GetObjectPath().value() << "'.";
77 Update();
78}
79
80void PeerdClient::OnPeerdOffline(const dbus::ObjectPath& object_path) {
81 peerd_manager_proxy_ = nullptr;
82 VLOG(1) << "Peerd manager is now offline.";
83}
84
85void PeerdClient::ExposeService() {
86 // Do nothing if peerd hasn't started yet.
87 if (peerd_manager_proxy_ == nullptr)
88 return;
89 VLOG(1) << "Starting peerd advertising.";
90 CHECK_NE(port_, 0);
Vitaly Buka7042c582015-07-30 17:02:14 -070091 CHECK(!txt_.empty());
Alex Vakulenko41705852015-10-13 10:12:06 -070092 std::map<std::string, brillo::Any> mdns_options{
93 {"port", brillo::Any{port_}},
Vitaly Buka7042c582015-07-30 17:02:14 -070094 };
95
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070096 std::map<std::string, std::string> txt;
97 for (const auto& record : txt_) {
Alex Vakulenko41705852015-10-13 10:12:06 -070098 auto name_value = brillo::string_utils::SplitAtFirst(record, "=");
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070099 CHECK(!name_value.second.empty());
100 txt.emplace(std::move(name_value));
101 }
102
103 published_ = true;
Vitaly Buka7042c582015-07-30 17:02:14 -0700104 peerd_manager_proxy_->ExposeServiceAsync(
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700105 kServiceName, txt, {{"mdns", mdns_options}}, base::Closure(),
Vitaly Buka7042c582015-07-30 17:02:14 -0700106 base::Bind(&OnError, "ExposeService"));
107}
108
109void PeerdClient::RemoveService() {
110 if (peerd_manager_proxy_ == nullptr)
111 return;
112
113 VLOG(1) << "Stopping peerd advertising.";
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700114 if (published_) {
115 published_ = false;
Vitaly Buka7042c582015-07-30 17:02:14 -0700116 peerd_manager_proxy_->RemoveExposedServiceAsync(
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700117 kServiceName, base::Closure(), base::Bind(&OnError, "RemoveService"));
Vitaly Buka7042c582015-07-30 17:02:14 -0700118 }
119}
120
121void PeerdClient::UpdateImpl() {
122 if (port_ == 0)
123 return RemoveService();
124 ExposeService();
125}
126
127} // namespace buffet