aboutsummaryrefslogtreecommitdiff
path: root/src/privet/publisher.cc
blob: db26b2652a0dcb3a3061af91053908facb1d5ee2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright 2015 The Weave 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 "src/privet/publisher.h"

#include <map>

#include <weave/error.h>
#include <weave/provider/dns_service_discovery.h>

#include "src/privet/cloud_delegate.h"
#include "src/privet/device_delegate.h"
#include "src/privet/device_ui_kind.h"
#include "src/privet/wifi_bootstrap_manager.h"
#include "src/privet/wifi_ssid_generator.h"
#include "src/string_utils.h"

namespace weave {
namespace privet {

namespace {

// The service type we'll expose via DNS-SD.
const char kPrivetServiceType[] = "_privet._tcp";

}  // namespace

Publisher::Publisher(const DeviceDelegate* device,
                     const CloudDelegate* cloud,
                     const WifiDelegate* wifi,
                     provider::DnsServiceDiscovery* dns_sd)
    : dns_sd_{dns_sd}, device_{device}, cloud_{cloud}, wifi_{wifi} {
  CHECK(device_);
  CHECK(cloud_);
  CHECK(dns_sd_);
  Update();
}

Publisher::~Publisher() {
  RemoveService();
}

void Publisher::Update() {
  if (device_->GetHttpEnpoint().first == 0)
    return RemoveService();
  ExposeService();
}

void Publisher::ExposeService() {
  std::string name{cloud_->GetName()};
  std::string model_id{cloud_->GetModelId()};
  DCHECK_EQ(model_id.size(), 5U);

  VLOG(2) << "DNS-SD update requested";
  const uint16_t port = device_->GetHttpEnpoint().first;
  DCHECK_NE(port, 0);

  std::vector<std::string> txt_record{
      {"txtvers=3"},
      {"ty=" + name},
      {"services=" + GetDeviceUiKind(model_id)},
      {"id=" + cloud_->GetDeviceId()},
      {"mmid=" + model_id},
      {"flags=" + WifiSsidGenerator{cloud_, wifi_}.GenerateFlags()},
  };

  if (device_->GetHttpsEnpoint().first > 0)
    txt_record.emplace_back("https=" +
                            std::to_string(device_->GetHttpsEnpoint().first));

  if (!cloud_->GetCloudId().empty())
    txt_record.emplace_back("gcd_id=" + cloud_->GetCloudId());

  if (!cloud_->GetDescription().empty())
    txt_record.emplace_back("note=" + cloud_->GetDescription());

  auto new_data = std::make_pair(port, txt_record);
  if (published_ == new_data)
    return;

  VLOG(1) << "Updating service using DNS-SD, port: " << port;
  published_ = new_data;
  dns_sd_->PublishService(kPrivetServiceType, port, txt_record);
}

void Publisher::RemoveService() {
  if (!published_.first)
    return;
  published_ = {};
  VLOG(1) << "Stopping service publishing";
  dns_sd_->StopPublishing(kPrivetServiceType);
}

}  // namespace privet
}  // namespace weave