1 // Copyright 2015 The Weave 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 "src/privet/publisher.h"
6
7 #include <map>
8
9 #include <weave/error.h>
10 #include <weave/provider/dns_service_discovery.h>
11
12 #include "src/privet/cloud_delegate.h"
13 #include "src/privet/device_delegate.h"
14 #include "src/privet/device_ui_kind.h"
15 #include "src/privet/wifi_bootstrap_manager.h"
16 #include "src/privet/wifi_ssid_generator.h"
17 #include "src/string_utils.h"
18
19 namespace weave {
20 namespace privet {
21
22 namespace {
23
24 // The service type we'll expose via DNS-SD.
25 const char kPrivetServiceType[] = "_privet._tcp";
26
27 } // namespace
28
Publisher(const DeviceDelegate * device,const CloudDelegate * cloud,const WifiDelegate * wifi,provider::DnsServiceDiscovery * dns_sd)29 Publisher::Publisher(const DeviceDelegate* device,
30 const CloudDelegate* cloud,
31 const WifiDelegate* wifi,
32 provider::DnsServiceDiscovery* dns_sd)
33 : dns_sd_{dns_sd}, device_{device}, cloud_{cloud}, wifi_{wifi} {
34 CHECK(device_);
35 CHECK(cloud_);
36 CHECK(dns_sd_);
37 Update();
38 }
39
~Publisher()40 Publisher::~Publisher() {
41 RemoveService();
42 }
43
Update()44 void Publisher::Update() {
45 if (device_->GetHttpEnpoint().first == 0)
46 return RemoveService();
47 ExposeService();
48 }
49
ExposeService()50 void Publisher::ExposeService() {
51 std::string name{cloud_->GetName()};
52 std::string model_id{cloud_->GetModelId()};
53 DCHECK_EQ(model_id.size(), 5U);
54
55 VLOG(2) << "DNS-SD update requested";
56 const uint16_t port = device_->GetHttpEnpoint().first;
57 DCHECK_NE(port, 0);
58
59 std::vector<std::string> txt_record{
60 {"txtvers=3"},
61 {"ty=" + name},
62 {"services=" + GetDeviceUiKind(model_id)},
63 {"id=" + cloud_->GetDeviceId()},
64 {"mmid=" + model_id},
65 {"flags=" + WifiSsidGenerator{cloud_, wifi_}.GenerateFlags()},
66 };
67
68 if (!cloud_->GetCloudId().empty())
69 txt_record.emplace_back("gcd_id=" + cloud_->GetCloudId());
70
71 if (!cloud_->GetDescription().empty())
72 txt_record.emplace_back("note=" + cloud_->GetDescription());
73
74 auto new_data = std::make_pair(port, txt_record);
75 if (published_ == new_data)
76 return;
77
78 VLOG(1) << "Updating service using DNS-SD, port: " << port;
79 published_ = new_data;
80 dns_sd_->PublishService(kPrivetServiceType, port, txt_record);
81 }
82
RemoveService()83 void Publisher::RemoveService() {
84 if (!published_.first)
85 return;
86 published_ = {};
87 VLOG(1) << "Stopping service publishing";
88 dns_sd_->StopPublishing(kPrivetServiceType);
89 }
90
91 } // namespace privet
92 } // namespace weave
93