| // 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 |