| // Copyright 2014 The Chromium OS 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 "libweave/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 "libweave/src/device_registration_info.h" |
| #include "libweave/src/http_constants.h" |
| #include "libweave/src/privet/cloud_delegate.h" |
| #include "libweave/src/privet/constants.h" |
| #include "libweave/src/privet/device_delegate.h" |
| #include "libweave/src/privet/privet_handler.h" |
| #include "libweave/src/privet/publisher.h" |
| #include "libweave/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() {} |
| |
| Manager::~Manager() {} |
| |
| void Manager::Start(const Device::Options& options, |
| TaskRunner* task_runner, |
| Network* network, |
| DnsServiceDiscovery* dns_sd, |
| HttpServer* http_server, |
| Wifi* wifi, |
| DeviceRegistrationInfo* device, |
| CommandManager* command_manager, |
| StateManager* state_manager) { |
| disable_security_ = options.disable_security; |
| |
| device_ = DeviceDelegate::CreateDefault(); |
| cloud_ = CloudDelegate::CreateDefault(task_runner, device, command_manager, |
| state_manager); |
| cloud_observer_.Add(cloud_.get()); |
| security_.reset(new SecurityManager(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( |
| options.test_privet_ssid, device->GetMutableConfig(), task_runner, |
| network, wifi, cloud_.get())); |
| wifi_bootstrap_manager_->Init(); |
| } |
| |
| 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(), publisher_.get())); |
| |
| http_server->AddOnStateChangedCallback(base::Bind( |
| &Manager::OnHttpServerStatusChanged, weak_ptr_factory_.GetWeakPtr())); |
| http_server->AddRequestHandler("/privet/", |
| base::Bind(&Manager::PrivetRequestHandler, |
| weak_ptr_factory_.GetWeakPtr())); |
| if (options.enable_ping) { |
| http_server->AddRequestHandler("/privet/ping", |
| base::Bind(&Manager::HelloWorldHandler, |
| 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( |
| const HttpServer::Request& request, |
| const HttpServer::OnReplyCallback& callback) { |
| std::string auth_header = request.GetFirstHeader(http::kAuthorization); |
| if (auth_header.empty() && disable_security_) |
| auth_header = "Privet anonymous"; |
| std::string data(request.GetData().begin(), request.GetData().end()); |
| VLOG(3) << "Input: " << data; |
| |
| base::DictionaryValue empty; |
| std::unique_ptr<base::Value> value; |
| const base::DictionaryValue* dictionary = ∅ |
| |
| std::string content_type = |
| SplitAtFirst(request.GetFirstHeader(http::kContentType), ";", true).first; |
| if (content_type == http::kJson) { |
| value.reset(base::JSONReader::Read(data).release()); |
| if (value) |
| value->GetAsDictionary(&dictionary); |
| } |
| |
| privet_handler_->HandleRequest( |
| request.GetPath(), auth_header, dictionary, |
| base::Bind(&Manager::PrivetResponseHandler, |
| weak_ptr_factory_.GetWeakPtr(), callback)); |
| } |
| |
| void Manager::PrivetResponseHandler(const HttpServer::OnReplyCallback& callback, |
| 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); |
| callback.Run(status, data, http::kJson); |
| } |
| |
| void Manager::HelloWorldHandler(const HttpServer::Request& request, |
| const HttpServer::OnReplyCallback& callback) { |
| callback.Run(http::kOk, "Hello, world!", http::kPlain); |
| } |
| |
| void Manager::OnChanged() { |
| if (publisher_) |
| publisher_->Update(); |
| } |
| |
| void Manager::OnConnectivityChanged() { |
| OnChanged(); |
| } |
| |
| void Manager::OnHttpServerStatusChanged(const HttpServer& server) { |
| if (device_->GetHttpEnpoint().first != server.GetHttpPort()) { |
| device_->SetHttpPort(server.GetHttpPort()); |
| if (publisher_) // Only HTTP port is published |
| publisher_->Update(); |
| } |
| device_->SetHttpsPort(server.GetHttpsPort()); |
| security_->SetCertificateFingerprint(server.GetHttpsCertificateFingerprint()); |
| } |
| |
| } // namespace privet |
| } // namespace weave |