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/privet_manager.h"
6
7#include <memory>
8#include <set>
9#include <string>
10
11#include <base/bind.h>
12#include <base/json/json_reader.h>
13#include <base/json/json_writer.h>
14#include <base/memory/weak_ptr.h>
15#include <base/scoped_observer.h>
16#include <base/strings/string_number_conversions.h>
17#include <base/values.h>
18#include <weave/provider/network.h>
19
20#include "src/bind_lambda.h"
21#include "src/component_manager.h"
22#include "src/device_registration_info.h"
23#include "src/http_constants.h"
24#include "src/privet/auth_manager.h"
25#include "src/privet/cloud_delegate.h"
26#include "src/privet/constants.h"
27#include "src/privet/device_delegate.h"
28#include "src/privet/privet_handler.h"
29#include "src/privet/publisher.h"
30#include "src/streams.h"
31#include "src/string_utils.h"
32
33namespace weave {
34namespace privet {
35
36using provider::TaskRunner;
37using provider::Network;
38using provider::DnsServiceDiscovery;
39using provider::HttpServer;
40using provider::Wifi;
41
42Manager::Manager(TaskRunner* task_runner) : task_runner_{task_runner} {}
43
44Manager::~Manager() {}
45
46void Manager::Start(Network* network,
47                    DnsServiceDiscovery* dns_sd,
48                    HttpServer* http_server,
49                    Wifi* wifi,
50                    AuthManager* auth_manager,
51                    DeviceRegistrationInfo* device,
52                    ComponentManager* component_manager) {
53  CHECK(auth_manager);
54  CHECK(device);
55
56  device_ = DeviceDelegate::CreateDefault(
57      task_runner_, http_server->GetHttpPort(), http_server->GetHttpsPort(),
58      http_server->GetRequestTimeout());
59  cloud_ =
60      CloudDelegate::CreateDefault(task_runner_, device, component_manager);
61  cloud_observer_.Add(cloud_.get());
62
63  security_.reset(new SecurityManager(device->GetMutableConfig(), auth_manager,
64                                      task_runner_));
65  network->AddConnectionChangedCallback(
66      base::Bind(&Manager::OnConnectivityChanged, base::Unretained(this)));
67
68  if (wifi && device->GetSettings().wifi_auto_setup_enabled) {
69    VLOG(1) << "Enabling WiFi bootstrapping.";
70    wifi_bootstrap_manager_.reset(new WifiBootstrapManager(
71        device->GetMutableConfig(), task_runner_, network, wifi, cloud_.get()));
72    wifi_bootstrap_manager_->Init();
73  }
74
75  if (dns_sd) {
76    publisher_.reset(new Publisher(device_.get(), cloud_.get(),
77                                   wifi_bootstrap_manager_.get(), dns_sd));
78  }
79
80  privet_handler_.reset(new PrivetHandler(cloud_.get(), device_.get(),
81                                          security_.get(),
82                                          wifi_bootstrap_manager_.get()));
83
84  for (const auto& path : privet_handler_->GetHttpPaths()) {
85    http_server->AddHttpRequestHandler(
86        path, base::Bind(&Manager::PrivetRequestHandler,
87                         weak_ptr_factory_.GetWeakPtr()));
88  }
89
90  for (const auto& path : privet_handler_->GetHttpsPaths()) {
91    http_server->AddHttpsRequestHandler(
92        path, base::Bind(&Manager::PrivetRequestHandler,
93                         weak_ptr_factory_.GetWeakPtr()));
94  }
95}
96
97std::string Manager::GetCurrentlyConnectedSsid() const {
98  return wifi_bootstrap_manager_
99             ? wifi_bootstrap_manager_->GetCurrentlyConnectedSsid()
100             : "";
101}
102
103void Manager::AddOnPairingChangedCallbacks(
104    const SecurityManager::PairingStartListener& on_start,
105    const SecurityManager::PairingEndListener& on_end) {
106  security_->RegisterPairingListeners(on_start, on_end);
107}
108
109void Manager::OnDeviceInfoChanged() {
110  OnChanged();
111}
112
113void Manager::PrivetRequestHandler(
114    std::unique_ptr<provider::HttpServer::Request> req) {
115  std::shared_ptr<provider::HttpServer::Request> request{std::move(req)};
116
117  std::string content_type =
118      SplitAtFirst(request->GetFirstHeader(http::kContentType), ";", true)
119          .first;
120
121  return PrivetRequestHandlerWithData(request, content_type == http::kJson
122                                                   ? request->GetData()
123                                                   : std::string{});
124}
125
126void Manager::PrivetRequestHandlerWithData(
127    const std::shared_ptr<provider::HttpServer::Request>& request,
128    const std::string& data) {
129  std::string auth_header = request->GetFirstHeader(http::kAuthorization);
130  base::DictionaryValue empty;
131  auto value = base::JSONReader::Read(data);
132  const base::DictionaryValue* dictionary = &empty;
133  if (value)
134    value->GetAsDictionary(&dictionary);
135
136  VLOG(3) << "Input: " << *dictionary;
137
138  privet_handler_->HandleRequest(
139      request->GetPath(), auth_header, dictionary,
140      base::Bind(&Manager::PrivetResponseHandler,
141                 weak_ptr_factory_.GetWeakPtr(), request));
142}
143
144void Manager::PrivetResponseHandler(
145    const std::shared_ptr<provider::HttpServer::Request>& request,
146    int status,
147    const base::DictionaryValue& output) {
148  VLOG(3) << "status: " << status << ", Output: " << output;
149  std::string data;
150  base::JSONWriter::WriteWithOptions(
151      output, base::JSONWriter::OPTIONS_PRETTY_PRINT, &data);
152  request->SendReply(status, data, http::kJson);
153}
154
155void Manager::OnChanged() {
156  VLOG(1) << "Manager::OnChanged";
157  if (publisher_)
158    publisher_->Update();
159}
160
161void Manager::OnConnectivityChanged() {
162  OnChanged();
163}
164
165}  // namespace privet
166}  // namespace weave
167