|  | // 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/privet_manager.h" | 
|  |  | 
|  | #include <memory> | 
|  | #include <set> | 
|  | #include <string> | 
|  |  | 
|  | #include <base/bind.h> | 
|  | #include <base/json/json_reader.h> | 
|  | #include <base/json/json_writer.h> | 
|  | #include <base/memory/weak_ptr.h> | 
|  | #include <base/scoped_observer.h> | 
|  | #include <base/strings/string_number_conversions.h> | 
|  | #include <base/values.h> | 
|  | #include <weave/provider/network.h> | 
|  |  | 
|  | #include "src/bind_lambda.h" | 
|  | #include "src/component_manager.h" | 
|  | #include "src/device_registration_info.h" | 
|  | #include "src/http_constants.h" | 
|  | #include "src/privet/auth_manager.h" | 
|  | #include "src/privet/cloud_delegate.h" | 
|  | #include "src/privet/constants.h" | 
|  | #include "src/privet/device_delegate.h" | 
|  | #include "src/privet/privet_handler.h" | 
|  | #include "src/privet/publisher.h" | 
|  | #include "src/streams.h" | 
|  | #include "src/string_utils.h" | 
|  |  | 
|  | namespace weave { | 
|  | namespace privet { | 
|  |  | 
|  | using provider::TaskRunner; | 
|  | using provider::Network; | 
|  | using provider::DnsServiceDiscovery; | 
|  | using provider::HttpServer; | 
|  | using provider::Wifi; | 
|  |  | 
|  | Manager::Manager(TaskRunner* task_runner) : task_runner_{task_runner} {} | 
|  |  | 
|  | Manager::~Manager() {} | 
|  |  | 
|  | void Manager::Start(Network* network, | 
|  | DnsServiceDiscovery* dns_sd, | 
|  | HttpServer* http_server, | 
|  | Wifi* wifi, | 
|  | AuthManager* auth_manager, | 
|  | DeviceRegistrationInfo* device, | 
|  | ComponentManager* component_manager) { | 
|  | CHECK(auth_manager); | 
|  | CHECK(device); | 
|  |  | 
|  | disable_security_ = device->GetSettings().disable_security; | 
|  |  | 
|  | device_ = DeviceDelegate::CreateDefault( | 
|  | task_runner_, http_server->GetHttpPort(), http_server->GetHttpsPort(), | 
|  | http_server->GetRequestTimeout()); | 
|  | cloud_ = | 
|  | CloudDelegate::CreateDefault(task_runner_, device, component_manager); | 
|  | cloud_observer_.Add(cloud_.get()); | 
|  |  | 
|  | security_.reset(new SecurityManager( | 
|  | auth_manager, device->GetSettings().pairing_modes, | 
|  | device->GetSettings().embedded_code, disable_security_, task_runner_)); | 
|  | network->AddConnectionChangedCallback( | 
|  | base::Bind(&Manager::OnConnectivityChanged, base::Unretained(this))); | 
|  |  | 
|  | if (wifi && device->GetSettings().wifi_auto_setup_enabled) { | 
|  | VLOG(1) << "Enabling WiFi bootstrapping."; | 
|  | wifi_bootstrap_manager_.reset(new WifiBootstrapManager( | 
|  | device->GetMutableConfig(), task_runner_, network, wifi, cloud_.get())); | 
|  | wifi_bootstrap_manager_->Init(); | 
|  | } | 
|  |  | 
|  | if (dns_sd) { | 
|  | publisher_.reset(new Publisher(device_.get(), cloud_.get(), | 
|  | wifi_bootstrap_manager_.get(), dns_sd)); | 
|  | } | 
|  |  | 
|  | privet_handler_.reset(new PrivetHandler(cloud_.get(), device_.get(), | 
|  | security_.get(), | 
|  | wifi_bootstrap_manager_.get())); | 
|  |  | 
|  | for (const auto& path : privet_handler_->GetHttpPaths()) { | 
|  | http_server->AddHttpRequestHandler( | 
|  | path, base::Bind(&Manager::PrivetRequestHandler, | 
|  | weak_ptr_factory_.GetWeakPtr())); | 
|  | } | 
|  |  | 
|  | for (const auto& path : privet_handler_->GetHttpsPaths()) { | 
|  | http_server->AddHttpsRequestHandler( | 
|  | path, base::Bind(&Manager::PrivetRequestHandler, | 
|  | weak_ptr_factory_.GetWeakPtr())); | 
|  | } | 
|  | } | 
|  |  | 
|  | std::string Manager::GetCurrentlyConnectedSsid() const { | 
|  | return wifi_bootstrap_manager_ | 
|  | ? wifi_bootstrap_manager_->GetCurrentlyConnectedSsid() | 
|  | : ""; | 
|  | } | 
|  |  | 
|  | void Manager::AddOnPairingChangedCallbacks( | 
|  | const SecurityManager::PairingStartListener& on_start, | 
|  | const SecurityManager::PairingEndListener& on_end) { | 
|  | security_->RegisterPairingListeners(on_start, on_end); | 
|  | } | 
|  |  | 
|  | void Manager::OnDeviceInfoChanged() { | 
|  | OnChanged(); | 
|  | } | 
|  |  | 
|  | void Manager::PrivetRequestHandler( | 
|  | std::unique_ptr<provider::HttpServer::Request> req) { | 
|  | std::shared_ptr<provider::HttpServer::Request> request{std::move(req)}; | 
|  |  | 
|  | std::string content_type = | 
|  | SplitAtFirst(request->GetFirstHeader(http::kContentType), ";", true) | 
|  | .first; | 
|  |  | 
|  | return PrivetRequestHandlerWithData(request, content_type == http::kJson | 
|  | ? request->GetData() | 
|  | : std::string{}); | 
|  | } | 
|  |  | 
|  | void Manager::PrivetRequestHandlerWithData( | 
|  | const std::shared_ptr<provider::HttpServer::Request>& request, | 
|  | const std::string& data) { | 
|  | std::string auth_header = request->GetFirstHeader(http::kAuthorization); | 
|  | if (auth_header.empty() && disable_security_) | 
|  | auth_header = "Privet anonymous"; | 
|  |  | 
|  | base::DictionaryValue empty; | 
|  | auto value = base::JSONReader::Read(data); | 
|  | const base::DictionaryValue* dictionary = ∅ | 
|  | if (value) | 
|  | value->GetAsDictionary(&dictionary); | 
|  |  | 
|  | VLOG(3) << "Input: " << *dictionary; | 
|  |  | 
|  | privet_handler_->HandleRequest( | 
|  | request->GetPath(), auth_header, dictionary, | 
|  | base::Bind(&Manager::PrivetResponseHandler, | 
|  | weak_ptr_factory_.GetWeakPtr(), request)); | 
|  | } | 
|  |  | 
|  | void Manager::PrivetResponseHandler( | 
|  | const std::shared_ptr<provider::HttpServer::Request>& request, | 
|  | int status, | 
|  | const base::DictionaryValue& output) { | 
|  | VLOG(3) << "status: " << status << ", Output: " << output; | 
|  | std::string data; | 
|  | base::JSONWriter::WriteWithOptions( | 
|  | output, base::JSONWriter::OPTIONS_PRETTY_PRINT, &data); | 
|  | request->SendReply(status, data, http::kJson); | 
|  | } | 
|  |  | 
|  | void Manager::OnChanged() { | 
|  | VLOG(1) << "Manager::OnChanged"; | 
|  | if (publisher_) | 
|  | publisher_->Update(); | 
|  | } | 
|  |  | 
|  | void Manager::OnConnectivityChanged() { | 
|  | OnChanged(); | 
|  | } | 
|  |  | 
|  | }  // namespace privet | 
|  | }  // namespace weave |