Home | History | Annotate | Download | only in privet
      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 
     33 namespace weave {
     34 namespace privet {
     35 
     36 using provider::TaskRunner;
     37 using provider::Network;
     38 using provider::DnsServiceDiscovery;
     39 using provider::HttpServer;
     40 using provider::Wifi;
     41 
     42 Manager::Manager(TaskRunner* task_runner) : task_runner_{task_runner} {}
     43 
     44 Manager::~Manager() {}
     45 
     46 void 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 
     97 std::string Manager::GetCurrentlyConnectedSsid() const {
     98   return wifi_bootstrap_manager_
     99              ? wifi_bootstrap_manager_->GetCurrentlyConnectedSsid()
    100              : "";
    101 }
    102 
    103 void Manager::AddOnPairingChangedCallbacks(
    104     const SecurityManager::PairingStartListener& on_start,
    105     const SecurityManager::PairingEndListener& on_end) {
    106   security_->RegisterPairingListeners(on_start, on_end);
    107 }
    108 
    109 void Manager::OnDeviceInfoChanged() {
    110   OnChanged();
    111 }
    112 
    113 void 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 
    126 void 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 
    144 void 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 
    155 void Manager::OnChanged() {
    156   VLOG(1) << "Manager::OnChanged";
    157   if (publisher_)
    158     publisher_->Update();
    159 }
    160 
    161 void Manager::OnConnectivityChanged() {
    162   OnChanged();
    163 }
    164 
    165 }  // namespace privet
    166 }  // namespace weave
    167