blob: 7a9757018a6c629790102244795c677d71a01797 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Vitaly Buka7b6b3f02015-06-09 15:50:20 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/privet/privet_manager.h"
Vitaly Buka7b6b3f02015-06-09 15:50:20 -07006
7#include <memory>
8#include <set>
9#include <string>
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070010
11#include <base/bind.h>
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070012#include <base/json/json_reader.h>
Vitaly Buka95d0e452015-08-01 00:17:09 -070013#include <base/json/json_writer.h>
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070014#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>
Vitaly Buka1e363672015-09-25 14:01:16 -070018#include <weave/provider/network.h>
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070019
Vitaly Buka5fe76092015-10-08 13:37:53 -070020#include "src/bind_lambda.h"
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020021#include "src/device_registration_info.h"
22#include "src/http_constants.h"
23#include "src/privet/cloud_delegate.h"
24#include "src/privet/constants.h"
25#include "src/privet/device_delegate.h"
26#include "src/privet/privet_handler.h"
27#include "src/privet/publisher.h"
Vitaly Buka5fe76092015-10-08 13:37:53 -070028#include "src/streams.h"
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020029#include "src/string_utils.h"
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070030
Vitaly Bukab6f015a2015-07-09 14:59:23 -070031namespace weave {
32namespace privet {
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070033
Vitaly Buka1e363672015-09-25 14:01:16 -070034using provider::TaskRunner;
35using provider::Network;
36using provider::DnsServiceDiscovery;
37using provider::HttpServer;
38using provider::Wifi;
39
Vitaly Buka5fe76092015-10-08 13:37:53 -070040Manager::Manager(TaskRunner* task_runner) : task_runner_{task_runner} {}
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070041
Vitaly Buka4ebd3292015-09-23 18:04:17 -070042Manager::~Manager() {}
Vitaly Bukaae96cc32015-06-09 17:22:18 -070043
Vitaly Buka5fe76092015-10-08 13:37:53 -070044void Manager::Start(Network* network,
Vitaly Buka1e363672015-09-25 14:01:16 -070045 DnsServiceDiscovery* dns_sd,
Vitaly Buka2ad97342015-08-02 20:57:43 -070046 HttpServer* http_server,
Vitaly Buka1e363672015-09-25 14:01:16 -070047 Wifi* wifi,
Vitaly Bukab6f015a2015-07-09 14:59:23 -070048 DeviceRegistrationInfo* device,
49 CommandManager* command_manager,
Vitaly Buka8e2f4162015-08-02 21:14:50 -070050 StateManager* state_manager) {
Vitaly Buka41a90d62015-09-29 16:58:39 -070051 disable_security_ = device->GetSettings().disable_security;
Vitaly Bukaae96cc32015-06-09 17:22:18 -070052
Vitaly Buka1f2e4f32015-10-08 10:13:52 -070053 device_ = DeviceDelegate::CreateDefault(http_server->GetHttpPort(),
54 http_server->GetHttpsPort());
Vitaly Buka5fe76092015-10-08 13:37:53 -070055 cloud_ = CloudDelegate::CreateDefault(task_runner_, device, command_manager,
Vitaly Bukaf9630fb2015-08-12 21:15:40 -070056 state_manager);
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070057 cloud_observer_.Add(cloud_.get());
Vitaly Buka8589b052015-09-29 00:46:14 -070058 security_.reset(new SecurityManager(
59 device->GetSettings().secret, device->GetSettings().pairing_modes,
Vitaly Buka5fe76092015-10-08 13:37:53 -070060 device->GetSettings().embedded_code, disable_security_, task_runner_));
Vitaly Buka1f2e4f32015-10-08 10:13:52 -070061 security_->SetCertificateFingerprint(
62 http_server->GetHttpsCertificateFingerprint());
Vitaly Buka8589b052015-09-29 00:46:14 -070063 if (device->GetSettings().secret.empty()) {
64 // TODO(vitalybuka): Post all Config::Transaction to avoid following.
Vitaly Buka5fe76092015-10-08 13:37:53 -070065 task_runner_->PostDelayedTask(
Vitaly Buka8589b052015-09-29 00:46:14 -070066 FROM_HERE,
67 base::Bind(&Manager::SaveDeviceSecret, weak_ptr_factory_.GetWeakPtr(),
68 base::Unretained(device->GetMutableConfig())),
69 {});
70 }
Vitaly Buka3ab6f6e2015-09-24 13:16:16 -070071 network->AddConnectionChangedCallback(
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070072 base::Bind(&Manager::OnConnectivityChanged, base::Unretained(this)));
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070073
Vitaly Bukab1041e72015-09-21 15:26:51 -070074 if (wifi && device->GetSettings().wifi_auto_setup_enabled) {
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070075 VLOG(1) << "Enabling WiFi bootstrapping.";
Vitaly Bukab56872f2015-06-21 18:39:34 -070076 wifi_bootstrap_manager_.reset(new WifiBootstrapManager(
Vitaly Buka5fe76092015-10-08 13:37:53 -070077 device->GetMutableConfig(), task_runner_, network, wifi, cloud_.get()));
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070078 wifi_bootstrap_manager_->Init();
79 }
80
Johan Euphrosine97b66ab2015-10-01 13:37:17 -070081 if (dns_sd) {
82 publisher_.reset(new Publisher(device_.get(), cloud_.get(),
83 wifi_bootstrap_manager_.get(), dns_sd));
84 }
Vitaly Buka7b6b3f02015-06-09 15:50:20 -070085
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070086 privet_handler_.reset(new PrivetHandler(cloud_.get(), device_.get(),
87 security_.get(),
88 wifi_bootstrap_manager_.get()));
Vitaly Bukaae96cc32015-06-09 17:22:18 -070089
Vitaly Buka1a39c812015-10-08 21:20:58 -070090 for (const auto& path : privet_handler_->GetHttpPaths()) {
91 http_server->AddHttpRequestHandler(
92 path, base::Bind(&Manager::PrivetRequestHandler,
93 weak_ptr_factory_.GetWeakPtr()));
94 }
95
96 for (const auto& path : privet_handler_->GetHttpsPaths()) {
97 http_server->AddHttpsRequestHandler(
98 path, base::Bind(&Manager::PrivetRequestHandler,
99 weak_ptr_factory_.GetWeakPtr()));
100 }
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700101}
102
Vitaly Buka0fa51e52015-07-10 00:12:25 -0700103std::string Manager::GetCurrentlyConnectedSsid() const {
104 return wifi_bootstrap_manager_
105 ? wifi_bootstrap_manager_->GetCurrentlyConnectedSsid()
106 : "";
107}
108
Vitaly Buka0fa51e52015-07-10 00:12:25 -0700109void Manager::AddOnPairingChangedCallbacks(
110 const SecurityManager::PairingStartListener& on_start,
111 const SecurityManager::PairingEndListener& on_end) {
112 security_->RegisterPairingListeners(on_start, on_end);
113}
114
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700115void Manager::OnDeviceInfoChanged() {
116 OnChanged();
Vitaly Buka7ab89ff2015-06-09 22:11:40 -0700117}
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700118
Vitaly Buka95d0e452015-08-01 00:17:09 -0700119void Manager::PrivetRequestHandler(
Vitaly Buka5fe76092015-10-08 13:37:53 -0700120 std::unique_ptr<provider::HttpServer::Request> req) {
121 std::shared_ptr<provider::HttpServer::Request> request{std::move(req)};
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700122
Vitaly Buka1da65992015-08-06 01:38:57 -0700123 std::string content_type =
Vitaly Buka5fe76092015-10-08 13:37:53 -0700124 SplitAtFirst(request->GetFirstHeader(http::kContentType), ";", true)
125 .first;
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700126
Vitaly Bukadfbd0c32015-10-08 22:47:57 -0700127 return PrivetRequestHandlerWithData(request, content_type == http::kJson
128 ? request->GetData()
129 : std::string{});
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700130}
131
Vitaly Buka5fe76092015-10-08 13:37:53 -0700132void Manager::PrivetRequestHandlerWithData(
133 const std::shared_ptr<provider::HttpServer::Request>& request,
134 const std::string& data) {
135 std::string auth_header = request->GetFirstHeader(http::kAuthorization);
136 if (auth_header.empty() && disable_security_)
137 auth_header = "Privet anonymous";
138
139 base::DictionaryValue empty;
140 auto value = base::JSONReader::Read(data);
141 const base::DictionaryValue* dictionary = &empty;
142 if (value)
143 value->GetAsDictionary(&dictionary);
144
145 VLOG(3) << "Input: " << *dictionary;
146
147 privet_handler_->HandleRequest(
148 request->GetPath(), auth_header, dictionary,
149 base::Bind(&Manager::PrivetResponseHandler,
150 weak_ptr_factory_.GetWeakPtr(), request));
151}
152
153void Manager::PrivetResponseHandler(
154 const std::shared_ptr<provider::HttpServer::Request>& request,
155 int status,
156 const base::DictionaryValue& output) {
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700157 VLOG(3) << "status: " << status << ", Output: " << output;
Vitaly Buka95d0e452015-08-01 00:17:09 -0700158 std::string data;
159 base::JSONWriter::WriteWithOptions(
160 output, base::JSONWriter::OPTIONS_PRETTY_PRINT, &data);
Vitaly Buka5fe76092015-10-08 13:37:53 -0700161 request->SendReply(status, data, http::kJson);
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700162}
163
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700164void Manager::OnChanged() {
Vitaly Buka7a350052015-10-10 23:58:20 -0700165 VLOG(1) << "Manager::OnChanged";
Vitaly Buka0bd32132015-07-30 15:54:48 -0700166 if (publisher_)
167 publisher_->Update();
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700168}
169
Vitaly Bukabf6840a2015-09-21 13:38:56 -0700170void Manager::OnConnectivityChanged() {
Vitaly Buka7b6b3f02015-06-09 15:50:20 -0700171 OnChanged();
172}
173
Vitaly Buka8589b052015-09-29 00:46:14 -0700174void Manager::SaveDeviceSecret(Config* config) {
175 Config::Transaction transaction(config);
176 transaction.set_secret(security_->GetSecret());
177}
178
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700179} // namespace privet
180} // namespace weave