blob: 88de4ca59a669669548794a464b983ea7c22c7e0 [file] [log] [blame]
Vitaly Bukacad20f02015-10-16 17:27:15 -07001// Copyright 2015 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Vitaly Buka7042c582015-07-30 17:02:14 -070014
15#include "buffet/peerd_client.h"
16
17#include <map>
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070018#include <vector>
Vitaly Buka7042c582015-07-30 17:02:14 -070019
20#include <base/message_loop/message_loop.h>
Alex Vakulenko41705852015-10-13 10:12:06 -070021#include <brillo/errors/error.h>
22#include <brillo/strings/string_utils.h>
Vitaly Buka7042c582015-07-30 17:02:14 -070023
24using org::chromium::peerd::PeerProxy;
25
26namespace buffet {
27
28namespace {
29
30// Commit changes only if no update request happened during the timeout.
31// Usually updates happen in batches, so we don't want to flood network with
32// updates relevant for a short amount of time.
33const int kCommitTimeoutSeconds = 1;
34
Alex Vakulenko41705852015-10-13 10:12:06 -070035void OnError(const std::string& operation, brillo::Error* error) {
Vitaly Buka7042c582015-07-30 17:02:14 -070036 LOG(ERROR) << operation << " failed:" << error->GetMessage();
37}
38
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070039const char kExpectedServiceType[] = "_privet._tcp";
40const char kServiceName[] = "privet";
41
Vitaly Buka7042c582015-07-30 17:02:14 -070042} // namespace
43
44PeerdClient::PeerdClient(const scoped_refptr<dbus::Bus>& bus)
45 : peerd_object_manager_proxy_{bus} {
46 peerd_object_manager_proxy_.SetManagerAddedCallback(
47 base::Bind(&PeerdClient::OnPeerdOnline, weak_ptr_factory_.GetWeakPtr()));
48 peerd_object_manager_proxy_.SetManagerRemovedCallback(
49 base::Bind(&PeerdClient::OnPeerdOffline, weak_ptr_factory_.GetWeakPtr()));
Vitaly Buka7042c582015-07-30 17:02:14 -070050}
51
52PeerdClient::~PeerdClient() {
53 RemoveService();
54}
55
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070056void PeerdClient::PublishService(const std::string& service_type,
57 uint16_t port,
58 const std::vector<std::string>& txt) {
Vitaly Buka7042c582015-07-30 17:02:14 -070059 // Only one service supported.
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070060 CHECK_EQ(service_type, kExpectedServiceType);
Vitaly Buka7042c582015-07-30 17:02:14 -070061 port_ = port;
62 txt_ = txt;
Vitaly Buka7042c582015-07-30 17:02:14 -070063 Update();
64}
65
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070066void PeerdClient::StopPublishing(const std::string& service_type) {
Vitaly Buka7042c582015-07-30 17:02:14 -070067 // Only one service supported.
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070068 CHECK_EQ(service_type, kExpectedServiceType);
Vitaly Buka7042c582015-07-30 17:02:14 -070069 port_ = 0;
Vitaly Buka7042c582015-07-30 17:02:14 -070070 Update();
71}
72
73void PeerdClient::Update() {
74 // Abort pending updates, and wait for more changes.
75 restart_weak_ptr_factory_.InvalidateWeakPtrs();
76 base::MessageLoop::current()->PostDelayedTask(
77 FROM_HERE, base::Bind(&PeerdClient::UpdateImpl,
78 restart_weak_ptr_factory_.GetWeakPtr()),
79 base::TimeDelta::FromSeconds(kCommitTimeoutSeconds));
80}
81
Vitaly Buka7042c582015-07-30 17:02:14 -070082void PeerdClient::OnPeerdOnline(
83 org::chromium::peerd::ManagerProxy* manager_proxy) {
84 peerd_manager_proxy_ = manager_proxy;
85 VLOG(1) << "Peerd manager is online at '"
86 << manager_proxy->GetObjectPath().value() << "'.";
87 Update();
88}
89
90void PeerdClient::OnPeerdOffline(const dbus::ObjectPath& object_path) {
91 peerd_manager_proxy_ = nullptr;
92 VLOG(1) << "Peerd manager is now offline.";
93}
94
95void PeerdClient::ExposeService() {
96 // Do nothing if peerd hasn't started yet.
97 if (peerd_manager_proxy_ == nullptr)
98 return;
99 VLOG(1) << "Starting peerd advertising.";
100 CHECK_NE(port_, 0);
Vitaly Buka7042c582015-07-30 17:02:14 -0700101 CHECK(!txt_.empty());
Alex Vakulenko41705852015-10-13 10:12:06 -0700102 std::map<std::string, brillo::Any> mdns_options{
103 {"port", brillo::Any{port_}},
Vitaly Buka7042c582015-07-30 17:02:14 -0700104 };
105
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700106 std::map<std::string, std::string> txt;
107 for (const auto& record : txt_) {
Alex Vakulenko41705852015-10-13 10:12:06 -0700108 auto name_value = brillo::string_utils::SplitAtFirst(record, "=");
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700109 CHECK(!name_value.second.empty());
110 txt.emplace(std::move(name_value));
111 }
112
113 published_ = true;
Vitaly Buka7042c582015-07-30 17:02:14 -0700114 peerd_manager_proxy_->ExposeServiceAsync(
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700115 kServiceName, txt, {{"mdns", mdns_options}}, base::Closure(),
Vitaly Buka7042c582015-07-30 17:02:14 -0700116 base::Bind(&OnError, "ExposeService"));
117}
118
119void PeerdClient::RemoveService() {
120 if (peerd_manager_proxy_ == nullptr)
121 return;
122
123 VLOG(1) << "Stopping peerd advertising.";
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700124 if (published_) {
125 published_ = false;
Vitaly Buka7042c582015-07-30 17:02:14 -0700126 peerd_manager_proxy_->RemoveExposedServiceAsync(
Alex Vakulenkoe32375b2015-09-28 08:55:40 -0700127 kServiceName, base::Closure(), base::Bind(&OnError, "RemoveService"));
Vitaly Buka7042c582015-07-30 17:02:14 -0700128 }
129}
130
131void PeerdClient::UpdateImpl() {
132 if (port_ == 0)
133 return RemoveService();
134 ExposeService();
135}
136
137} // namespace buffet