git merge --no-ff remotes/weave/master Change-Id: I15f4cbdaaedeeebceb69631265ce3b7862876405
diff --git a/libweave/README b/libweave/README index 7e519b9..b772553 100644 --- a/libweave/README +++ b/libweave/README
@@ -34,16 +34,16 @@ libweave_standalone.gyp libweave_common.gypi -Quick start on Ubuntu ---------------------- +Quick start on Debian/Ubuntu +---------------------------- Install prerequisites: - examples/ubuntu/prerequisites.sh + examples/prerequisites.sh Build library, tests, run tests, build example: - examples/ubuntu/build.sh + examples/build.sh Execute example: @@ -115,3 +115,7 @@ git push origin HEAD:refs/for/master Go to the url from the output of "push" and add reviewers. + +Known Issues +------------ +* No big-endian support. Pairing fails on big-endian hardware.
diff --git a/libweave/examples/ubuntu/build.sh b/libweave/examples/build.sh similarity index 82% rename from libweave/examples/ubuntu/build.sh rename to libweave/examples/build.sh index cc585cb..2bd398ef 100755 --- a/libweave/examples/ubuntu/build.sh +++ b/libweave/examples/build.sh
@@ -4,11 +4,11 @@ # found in the LICENSE file. DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) -ROOT_DIR=$(cd -P -- "$(dirname -- "$0")/../.." && pwd -P) +ROOT_DIR=$(cd -P -- "$(dirname -- "$0")/.." && pwd -P) cd $ROOT_DIR -gyp -Ilibweave_common.gypi --toplevel-dir=. --depth=. -f ninja $DIR/weave.gyp +gyp -Ilibweave_common.gypi --toplevel-dir=. --depth=. -f ninja $DIR/daemon/daemon.gyp if [ -z "$BUILD_CONFIG" ]; then export BUILD_CONFIG=Debug @@ -16,7 +16,7 @@ export BUILD_TARGET=$* if [ -z "$BUILD_TARGET" ]; then - export BUILD_TARGET="weave libweave_testrunner libweave_exports_testrunner" + export BUILD_TARGET="weave_daemon libweave_testrunner libweave_exports_testrunner" fi export CORES=`cat /proc/cpuinfo | grep processor | wc -l`
diff --git a/libweave/examples/ubuntu/README b/libweave/examples/daemon/README similarity index 94% rename from libweave/examples/ubuntu/README rename to libweave/examples/daemon/README index af67036..48a4e95 100644 --- a/libweave/examples/ubuntu/README +++ b/libweave/examples/daemon/README
@@ -5,9 +5,9 @@ Building -------- - prepare environment - examples/ubuntu/prerequisites.sh + examples/prerequisites.sh - build daemon - examples/ubuntu/build.sh + examples/build.sh - binaries for daemon is at out/Debug/weave @@ -48,7 +48,7 @@ ------------------------ - copy the ticket "id" generated above 93019287-6b26-04a0-22ee-d55ad23a4226 - - go to ubuntu terminal, register ubuntu and start daemon with + - go to terminal, register and start the daemon with sudo out/Debug/weave --registration_ticket=93019287-6b26-04a0-22ee-d55ad23a4226 @@ -75,8 +75,8 @@ chrome: https://chrome.google.com/webstore/detail/weave-device-manager/pcdgflbjckpjmlofgopidgdfonmnodfm [need your whitelisted EAP account] -Send Command to Ubuntu Device ------------------------------ +Send Command to the Daemon +-------------------------- - go to the oauthplayground used for registration ticket command in "Step 3", send base.identify with HTTP Method: POST
diff --git a/libweave/examples/daemon/daemon.gyp b/libweave/examples/daemon/daemon.gyp new file mode 100644 index 0000000..f421601 --- /dev/null +++ b/libweave/examples/daemon/daemon.gyp
@@ -0,0 +1,18 @@ +# 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. +{ + 'targets': [ + { + 'target_name': 'weave_daemon', + 'type': 'executable', + 'sources': [ + 'main.cc', + ], + 'dependencies': [ + '../../libweave_standalone.gyp:libweave', + '../provider/provider.gyp:libweave_provider', + ] + } + ] +}
diff --git a/libweave/examples/daemon/ledflasher_handler.h b/libweave/examples/daemon/ledflasher_handler.h new file mode 100644 index 0000000..812a3d4 --- /dev/null +++ b/libweave/examples/daemon/ledflasher_handler.h
@@ -0,0 +1,132 @@ +// 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 <weave/device.h> + +#include <base/bind.h> +#include <base/memory/weak_ptr.h> + +#include <bitset> + +namespace weave { +namespace examples { +namespace daemon { + +namespace { +// Supported LED count on this device +const size_t kLedCount = 3; +} // namespace + +// LedFlasherHandler is a complete command handler example that shows +// how to handle commands that modify device state. +class LedFlasherHandler { + public: + LedFlasherHandler() {} + void Register(Device* device) { + device_ = device; + + device->AddStateDefinitionsFromJson(R"({ + "_ledflasher": {"_leds": {"items": "boolean"}} + })"); + + device->SetStatePropertiesFromJson(R"({ + "_ledflasher":{"_leds": [false, false, false]} + })", + nullptr); + + device->AddCommandDefinitionsFromJson(R"({ + "_ledflasher": { + "_set":{ + "parameters": { + "_led": {"minimum": 1, "maximum": 3}, + "_on": "boolean" + } + }, + "_toggle":{ + "parameters": { + "_led": {"minimum": 1, "maximum": 3} + } + } + } + })"); + device->AddCommandHandler( + "_ledflasher._toggle", + base::Bind(&LedFlasherHandler::OnFlasherToggleCommand, + weak_ptr_factory_.GetWeakPtr())); + device->AddCommandHandler( + "_ledflasher._set", base::Bind(&LedFlasherHandler::OnFlasherSetCommand, + weak_ptr_factory_.GetWeakPtr())); + } + + private: + void OnFlasherSetCommand(const std::weak_ptr<Command>& command) { + auto cmd = command.lock(); + if (!cmd) + return; + LOG(INFO) << "received command: " << cmd->GetName(); + int32_t led_index = 0; + bool cmd_value = false; + if (cmd->GetParameters()->GetInteger("_led", &led_index) && + cmd->GetParameters()->GetBoolean("_on", &cmd_value)) { + // Display this command in terminal + LOG(INFO) << cmd->GetName() << " _led: " << led_index + << ", _on: " << (cmd_value ? "true" : "false"); + + led_index--; + int new_state = cmd_value ? 1 : 0; + int cur_state = led_status_[led_index]; + led_status_[led_index] = new_state; + + if (cmd_value != cur_state) { + UpdateLedState(); + } + cmd->Complete({}, nullptr); + return; + } + ErrorPtr error; + Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value", + "Invalid parameters"); + cmd->Abort(error.get(), nullptr); + } + + void OnFlasherToggleCommand(const std::weak_ptr<Command>& command) { + auto cmd = command.lock(); + if (!cmd) + return; + LOG(INFO) << "received command: " << cmd->GetName(); + int32_t led_index = 0; + if (cmd->GetParameters()->GetInteger("_led", &led_index)) { + LOG(INFO) << cmd->GetName() << " _led: " << led_index; + led_index--; + led_status_[led_index] = ~led_status_[led_index]; + + UpdateLedState(); + cmd->Complete({}, nullptr); + return; + } + ErrorPtr error; + Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value", + "Invalid parameters"); + cmd->Abort(error.get(), nullptr); + } + + void UpdateLedState(void) { + base::ListValue list; + for (uint32_t i = 0; i < led_status_.size(); i++) + list.AppendBoolean(led_status_[i] ? true : false); + + device_->SetStateProperty("_ledflasher._leds", list, nullptr); + } + + Device* device_{nullptr}; + + // Simulate LED status on this device so client app could explore + // Each bit represents one device, indexing from LSB + std::bitset<kLedCount> led_status_{0}; + base::WeakPtrFactory<LedFlasherHandler> weak_ptr_factory_{this}; +}; + +} // namespace daemon +} // namespace examples +} // namespace weave
diff --git a/libweave/examples/daemon/main.cc b/libweave/examples/daemon/main.cc new file mode 100644 index 0000000..263e730 --- /dev/null +++ b/libweave/examples/daemon/main.cc
@@ -0,0 +1,118 @@ +// 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 <weave/device.h> +#include <weave/error.h> + +#include <base/bind.h> + +#include "examples/daemon/ledflasher_handler.h" +#include "examples/daemon/sample_handler.h" + +#include "examples/provider/avahi_client.h" +#include "examples/provider/bluez_client.h" +#include "examples/provider/curl_http_client.h" +#include "examples/provider/event_http_server.h" +#include "examples/provider/event_network.h" +#include "examples/provider/event_task_runner.h" +#include "examples/provider/file_config_store.h" +#include "examples/provider/wifi_manager.h" + +namespace { + +// Supported LED count on this device +const size_t kLedCount = 3; + +void ShowUsage(const std::string& name) { + LOG(ERROR) << "\nUsage: " << name << " <option(s)>" + << "\nOptions:\n" + << "\t-h,--help Show this help message\n" + << "\t--v=LEVEL Logging level\n" + << "\t-b,--bootstrapping Force WiFi bootstrapping\n" + << "\t-d,--disable_security Disable privet security\n" + << "\t--registration_ticket=TICKET Register device with the " + "given ticket\n" + << "\t--disable_privet Disable local privet\n"; +} + +void OnRegisterDeviceDone(weave::Device* device, weave::ErrorPtr error) { + if (error) + LOG(ERROR) << "Fail to register device: " << error->GetMessage(); + else + LOG(INFO) << "Device registered: " << device->GetSettings().cloud_id; +} + +} // namespace + +int main(int argc, char** argv) { + bool force_bootstrapping = false; + bool disable_security = false; + bool disable_privet = false; + std::string registration_ticket; + for (int i = 1; i < argc; ++i) { + std::string arg = argv[i]; + if (arg == "-h" || arg == "--help") { + ShowUsage(argv[0]); + return 0; + } else if (arg == "-b" || arg == "--bootstrapping") { + force_bootstrapping = true; + } else if (arg == "-d" || arg == "--disable_security") { + disable_security = true; + } else if (arg == "--disable_privet") { + disable_privet = true; + } else if (arg.find("--registration_ticket") != std::string::npos) { + auto pos = arg.find("="); + if (pos == std::string::npos) { + ShowUsage(argv[0]); + return 1; + } + registration_ticket = arg.substr(pos + 1); + } else if (arg.find("--v") != std::string::npos) { + auto pos = arg.find("="); + if (pos == std::string::npos) { + ShowUsage(argv[0]); + return 1; + } + logging::SetMinLogLevel(-std::stoi(arg.substr(pos + 1))); + } else { + ShowUsage(argv[0]); + return 1; + } + } + + weave::examples::FileConfigStore config_store{disable_security}; + weave::examples::EventTaskRunner task_runner; + weave::examples::CurlHttpClient http_client{&task_runner}; + weave::examples::EventNetworkImpl network{&task_runner}; + weave::examples::BluetoothImpl bluetooth; + std::unique_ptr<weave::examples::AvahiClient> dns_sd; + std::unique_ptr<weave::examples::HttpServerImpl> http_server; + std::unique_ptr<weave::examples::WifiImpl> wifi; + + if (!disable_privet) { + dns_sd.reset(new weave::examples::AvahiClient); + http_server.reset(new weave::examples::HttpServerImpl{&task_runner}); + if (weave::examples::WifiImpl::HasWifiCapability()) + wifi.reset( + new weave::examples::WifiImpl{&task_runner, force_bootstrapping}); + } + std::unique_ptr<weave::Device> device{weave::Device::Create( + &config_store, &task_runner, &http_client, &network, dns_sd.get(), + http_server.get(), wifi.get(), &bluetooth)}; + + if (!registration_ticket.empty()) { + device->Register(registration_ticket, + base::Bind(&OnRegisterDeviceDone, device.get())); + } + + weave::examples::daemon::SampleHandler sample{&task_runner}; + weave::examples::daemon::LedFlasherHandler ledFlasher; + sample.Register(device.get()); + ledFlasher.Register(device.get()); + + task_runner.Run(); + + LOG(INFO) << "exit"; + return 0; +}
diff --git a/libweave/examples/daemon/sample_handler.h b/libweave/examples/daemon/sample_handler.h new file mode 100644 index 0000000..eca3452 --- /dev/null +++ b/libweave/examples/daemon/sample_handler.h
@@ -0,0 +1,160 @@ +// 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 <weave/device.h> +#include <weave/provider/task_runner.h> + +#include <base/bind.h> +#include <base/memory/weak_ptr.h> + +namespace weave { +namespace examples { +namespace daemon { + +// SampleHandler is a command handler example. +// It implements the following commands: +// - _hello: handle a command with an argument and set its results. +// - _ping: update device state. +// - _countdown: handle long running command and report progress. +class SampleHandler { + public: + SampleHandler(provider::TaskRunner* task_runner) + : task_runner_{task_runner} {} + void Register(Device* device) { + device_ = device; + + device->AddCommandDefinitionsFromJson(R"({ + "_sample": { + "_hello": { + "minimalRole": "user", + "parameters": { + "_name": "string" + }, + "results": { "_reply": "string" } + }, + "_ping": { + "minimalRole": "user", + "results": {} + }, + "_countdown": { + "minimalRole": "user", + "parameters": { + "_seconds": {"minimum": 1, "maximum": 25} + }, + "progress": { "_seconds_left": "integer"}, + "results": {} + } + } + })"); + + device->AddStateDefinitionsFromJson(R"({ + "_sample": {"_ping_count":"integer"} + })"); + + device->SetStatePropertiesFromJson(R"({ + "_sample": {"_ping_count": 0} + })", + nullptr); + + device->AddCommandHandler("_sample._hello", + base::Bind(&SampleHandler::OnHelloCommand, + weak_ptr_factory_.GetWeakPtr())); + device->AddCommandHandler("_sample._ping", + base::Bind(&SampleHandler::OnPingCommand, + weak_ptr_factory_.GetWeakPtr())); + device->AddCommandHandler("_sample._countdown", + base::Bind(&SampleHandler::OnCountdownCommand, + weak_ptr_factory_.GetWeakPtr())); + } + + private: + void OnHelloCommand(const std::weak_ptr<Command>& command) { + auto cmd = command.lock(); + if (!cmd) + return; + LOG(INFO) << "received command: " << cmd->GetName(); + + std::string name; + if (!cmd->GetParameters()->GetString("_name", &name)) { + ErrorPtr error; + Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value", + "Name is missing"); + cmd->Abort(error.get(), nullptr); + return; + } + + base::DictionaryValue result; + result.SetString("_reply", "Hello " + name); + cmd->Complete(result, nullptr); + LOG(INFO) << cmd->GetName() << " command finished: " << result; + } + + void OnPingCommand(const std::weak_ptr<Command>& command) { + auto cmd = command.lock(); + if (!cmd) + return; + LOG(INFO) << "received command: " << cmd->GetName(); + + base::DictionaryValue state; + state.SetInteger("_sample._ping_count", ++ping_count_); + device_->SetStateProperties(state, nullptr); + LOG(INFO) << "New state: " << *device_->GetState(); + + base::DictionaryValue result; + cmd->Complete(result, nullptr); + + LOG(INFO) << cmd->GetName() << " command finished: " << result; + } + + void OnCountdownCommand(const std::weak_ptr<Command>& command) { + auto cmd = command.lock(); + if (!cmd) + return; + LOG(INFO) << "received command: " << cmd->GetName(); + + int seconds; + if (!cmd->GetParameters()->GetInteger("_seconds", &seconds)) + seconds = 10; + + LOG(INFO) << "starting countdown"; + DoTick(cmd, seconds); + } + + void DoTick(const std::weak_ptr<Command>& command, int seconds) { + auto cmd = command.lock(); + if (!cmd) + return; + + if (seconds > 0) { + std::string todo; + cmd->GetParameters()->GetString("_todo", &todo); + LOG(INFO) << "countdown tick: " << seconds << " seconds left"; + + base::DictionaryValue progress; + progress.SetInteger("_seconds_left", seconds); + cmd->SetProgress(progress, nullptr); + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SampleHandler::DoTick, weak_ptr_factory_.GetWeakPtr(), + command, --seconds), + base::TimeDelta::FromSeconds(1)); + return; + } + + base::DictionaryValue result; + cmd->Complete(result, nullptr); + LOG(INFO) << "countdown finished"; + LOG(INFO) << cmd->GetName() << " command finished: " << result; + } + + Device* device_{nullptr}; + provider::TaskRunner* task_runner_{nullptr}; + + int ping_count_{0}; + base::WeakPtrFactory<SampleHandler> weak_ptr_factory_{this}; +}; + +} // namespace daemon +} // namespace examples +} // namespace weave
diff --git a/libweave/examples/ubuntu/prerequisites.sh b/libweave/examples/prerequisites.sh similarity index 96% rename from libweave/examples/ubuntu/prerequisites.sh rename to libweave/examples/prerequisites.sh index bc70fd3..d1661d0 100755 --- a/libweave/examples/ubuntu/prerequisites.sh +++ b/libweave/examples/prerequisites.sh
@@ -4,7 +4,7 @@ # found in the LICENSE file. DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) -ROOT_DIR=$(cd -P -- "$(dirname -- "$0")/../.." && pwd -P) +ROOT_DIR=$(cd -P -- "$(dirname -- "$0")/.." && pwd -P) sudo apt-get install ${APT_GET_OPTS} \ autoconf \
diff --git a/libweave/examples/ubuntu/avahi_client.cc b/libweave/examples/provider/avahi_client.cc similarity index 98% rename from libweave/examples/ubuntu/avahi_client.cc rename to libweave/examples/provider/avahi_client.cc index 3bc1823..18ad555 100644 --- a/libweave/examples/ubuntu/avahi_client.cc +++ b/libweave/examples/provider/avahi_client.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "examples/ubuntu/avahi_client.h" +#include "examples/provider/avahi_client.h" #include <cstdlib> #include <vector>
diff --git a/libweave/examples/ubuntu/avahi_client.h b/libweave/examples/provider/avahi_client.h similarity index 88% rename from libweave/examples/ubuntu/avahi_client.h rename to libweave/examples/provider/avahi_client.h index 64e0eb1..0ca28db 100644 --- a/libweave/examples/ubuntu/avahi_client.h +++ b/libweave/examples/provider/avahi_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_AVAHI_CLIENT_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_AVAHI_CLIENT_H_ +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_AVAHI_CLIENT_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_AVAHI_CLIENT_H_ #include <map> #include <string> @@ -44,4 +44,4 @@ } // namespace examples } // namespace weave -#endif // LIBWEAVE_EXAMPLES_UBUNTU_AVAHI_CLIENT_H_ +#endif // LIBWEAVE_EXAMPLES_PROVIDER_AVAHI_CLIENT_H_
diff --git a/libweave/examples/ubuntu/bluez_client.cc b/libweave/examples/provider/bluez_client.cc similarity index 87% rename from libweave/examples/ubuntu/bluez_client.cc rename to libweave/examples/provider/bluez_client.cc index 35defde..5342bcb 100644 --- a/libweave/examples/ubuntu/bluez_client.cc +++ b/libweave/examples/provider/bluez_client.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "examples/ubuntu/bluez_client.h" +#include "examples/provider/bluez_client.h" namespace weave { namespace examples {
diff --git a/libweave/examples/ubuntu/bluez_client.h b/libweave/examples/provider/bluez_client.h similarity index 74% rename from libweave/examples/ubuntu/bluez_client.h rename to libweave/examples/provider/bluez_client.h index e0bc2f2..922f325 100644 --- a/libweave/examples/ubuntu/bluez_client.h +++ b/libweave/examples/provider/bluez_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_BLUEZ_CLIENT_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_BLUEZ_CLIENT_H_ +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_BLUEZ_CLIENT_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_BLUEZ_CLIENT_H_ #include <weave/provider/bluetooth.h> @@ -21,4 +21,4 @@ } // namespace examples } // namespace weave -#endif // LIBWEAVE_EXAMPLES_UBUNTU_BLUEZ_CLIENT_H_ +#endif // LIBWEAVE_EXAMPLES_PROVIDER_BLUEZ_CLIENT_H_
diff --git a/libweave/examples/ubuntu/curl_http_client.cc b/libweave/examples/provider/curl_http_client.cc similarity index 94% rename from libweave/examples/ubuntu/curl_http_client.cc rename to libweave/examples/provider/curl_http_client.cc index 0ddf57a..b440f39 100644 --- a/libweave/examples/ubuntu/curl_http_client.cc +++ b/libweave/examples/provider/curl_http_client.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "examples/ubuntu/curl_http_client.h" +#include "examples/provider/curl_http_client.h" #include <base/bind.h> #include <curl/curl.h> @@ -46,11 +46,11 @@ switch (method) { case Method::kGet: - CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HTTPGET, 1L)); - break; + CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HTTPGET, 1L)); + break; case Method::kPost: - CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HTTPPOST, 1L)); - break; + CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HTTPPOST, 1L)); + break; case Method::kPatch: case Method::kPut: CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_CUSTOMREQUEST,
diff --git a/libweave/examples/ubuntu/curl_http_client.h b/libweave/examples/provider/curl_http_client.h similarity index 85% rename from libweave/examples/ubuntu/curl_http_client.h rename to libweave/examples/provider/curl_http_client.h index daf9b0c..b2f4bca 100644 --- a/libweave/examples/ubuntu/curl_http_client.h +++ b/libweave/examples/provider/curl_http_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_CURL_HTTP_CLIENT_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_CURL_HTTP_CLIENT_H_ +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_CURL_HTTP_CLIENT_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_CURL_HTTP_CLIENT_H_ #include <string> @@ -39,4 +39,4 @@ } // namespace examples } // namespace weave -#endif // LIBWEAVE_EXAMPLES_UBUNTU_CURL_HTTP_CLIENT_H_ +#endif // LIBWEAVE_EXAMPLES_PROVIDER_CURL_HTTP_CLIENT_H_
diff --git a/libweave/examples/ubuntu/event_http_client.cc b/libweave/examples/provider/event_http_client.cc similarity index 97% rename from libweave/examples/ubuntu/event_http_client.cc rename to libweave/examples/provider/event_http_client.cc index 22b68f2..b38bd55 100644 --- a/libweave/examples/ubuntu/event_http_client.cc +++ b/libweave/examples/provider/event_http_client.cc
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "examples/ubuntu/event_http_client.h" -#include "examples/ubuntu/event_task_runner.h" +#include "examples/provider/event_http_client.h" +#include "examples/provider/event_task_runner.h" #include <weave/enum_to_string.h>
diff --git a/libweave/examples/ubuntu/event_http_client.h b/libweave/examples/provider/event_http_client.h similarity index 83% rename from libweave/examples/ubuntu/event_http_client.h rename to libweave/examples/provider/event_http_client.h index 6ec2db6..7ad117e 100644 --- a/libweave/examples/ubuntu/event_http_client.h +++ b/libweave/examples/provider/event_http_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_EVENT_HTTP_CLIENT_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_EVENT_HTTP_CLIENT_H_ +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_CLIENT_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_CLIENT_H_ #include <string> @@ -35,4 +35,4 @@ } // namespace examples } // namespace weave -#endif // LIBWEAVE_EXAMPLES_UBUNTU_EVENT_HTTP_CLIENT_H_ +#endif // LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_CLIENT_H_
diff --git a/libweave/examples/ubuntu/event_http_server.cc b/libweave/examples/provider/event_http_server.cc similarity index 98% rename from libweave/examples/ubuntu/event_http_server.cc rename to libweave/examples/provider/event_http_server.cc index 95fea21..bb55c50 100644 --- a/libweave/examples/ubuntu/event_http_server.cc +++ b/libweave/examples/provider/event_http_server.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "examples/ubuntu/event_http_server.h" +#include "examples/provider/event_http_server.h" #include <vector> @@ -11,7 +11,7 @@ #include <event2/bufferevent_ssl.h> #include <openssl/err.h> -#include "examples/ubuntu/event_task_runner.h" +#include "examples/provider/event_task_runner.h" namespace weave { namespace examples { @@ -159,9 +159,7 @@ void HttpServerImpl::ProcessReply(std::shared_ptr<RequestImpl> request, int status_code, const std::string& data, - const std::string& mime_type) { - -} + const std::string& mime_type) {} void HttpServerImpl::AddHttpRequestHandler( const std::string& path,
diff --git a/libweave/examples/ubuntu/event_http_server.h b/libweave/examples/provider/event_http_server.h similarity index 93% rename from libweave/examples/ubuntu/event_http_server.h rename to libweave/examples/provider/event_http_server.h index 4828b72..e51c6f4 100644 --- a/libweave/examples/ubuntu/event_http_server.h +++ b/libweave/examples/provider/event_http_server.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_EVENT_HTTP_SERVER_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_EVENT_HTTP_SERVER_H_ +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_SERVER_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_SERVER_H_ #include <event2/http.h> #include <evhttp.h> @@ -70,4 +70,4 @@ } // namespace examples } // namespace weave -#endif // LIBWEAVE_EXAMPLES_UBUNTU_EVENT_HTTP_SERVER_H_ +#endif // LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_SERVER_H_
diff --git a/libweave/examples/ubuntu/event_network.cc b/libweave/examples/provider/event_network.cc similarity index 77% rename from libweave/examples/ubuntu/event_network.cc rename to libweave/examples/provider/event_network.cc index b411f80..d86db69 100644 --- a/libweave/examples/ubuntu/event_network.cc +++ b/libweave/examples/provider/event_network.cc
@@ -1,8 +1,8 @@ -// Copyright 2015 The Chromium OS Authors. All rights reserved. +// 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 "examples/ubuntu/event_network.h" +#include "examples/provider/event_network.h" #include <weave/enum_to_string.h> @@ -10,8 +10,8 @@ #include <event2/dns.h> #include <event2/bufferevent.h> -#include "examples/ubuntu/event_task_runner.h" -#include "examples/ubuntu/ssl_stream.h" +#include "examples/provider/event_task_runner.h" +#include "examples/provider/ssl_stream.h" namespace weave { namespace examples { @@ -19,6 +19,7 @@ namespace { const char kNetworkProbeHostname[] = "talk.google.com"; const int kNetworkProbePort = 5223; +const int kNetworkProbeTimeoutS = 2; } // namespace void EventNetworkImpl::Deleter::operator()(evdns_base* dns_base) { @@ -43,6 +44,8 @@ std::unique_ptr<bufferevent, Deleter> bev{ bufferevent_socket_new(task_runner_->GetEventBase(), -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS)}; + timeval timeout{kNetworkProbeTimeoutS, 0}; + bufferevent_set_timeouts(bev.get(), &timeout, &timeout); bufferevent_setcb( bev.get(), nullptr, nullptr, [](struct bufferevent* buf, short events, void* ctx) { @@ -77,10 +80,17 @@ void EventNetworkImpl::UpdateNetworkStateCallback( provider::Network::State state) { - network_state_ = state; - LOG(INFO) << "network state updated: " << weave::EnumToString(state); - for (const auto& cb : callbacks_) - cb.Run(); + if (state != network_state_) { + LOG(INFO) << "network state updated: " << weave::EnumToString(state); + network_state_ = state; + + // In general it's better to send false notification than miss one. + // However current implementation can only send them very often on every + // UpdateNetworkStateCallback or just here, guarder with this if condition. + for (const auto& cb : callbacks_) + cb.Run(); + } + // TODO(proppy): use netlink interface event instead of polling task_runner_->PostDelayedTask( FROM_HERE, base::Bind(&EventNetworkImpl::UpdateNetworkState, @@ -95,20 +105,7 @@ void EventNetworkImpl::OpenSslSocket(const std::string& host, uint16_t port, const OpenSslSocketCallback& callback) { - // Connect to SSL port instead of upgrading to TLS. - std::unique_ptr<SSLStream> tls_stream{new SSLStream{task_runner_}}; - - if (tls_stream->Init(host, port)) { - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, base::Passed(&tls_stream), nullptr), - {}); - } else { - ErrorPtr error; - Error::AddTo(&error, FROM_HERE, "tls", "tls_init_failed", - "Failed to initialize TLS stream."); - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)), {}); - } + SSLStream::Connect(task_runner_, host, port, callback); } } // namespace examples
diff --git a/libweave/examples/ubuntu/event_network.h b/libweave/examples/provider/event_network.h similarity index 100% rename from libweave/examples/ubuntu/event_network.h rename to libweave/examples/provider/event_network.h
diff --git a/libweave/examples/ubuntu/event_task_runner.cc b/libweave/examples/provider/event_task_runner.cc similarity index 96% rename from libweave/examples/ubuntu/event_task_runner.cc rename to libweave/examples/provider/event_task_runner.cc index b781ff4..c14a934 100644 --- a/libweave/examples/ubuntu/event_task_runner.cc +++ b/libweave/examples/provider/event_task_runner.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "examples/ubuntu/event_task_runner.h" +#include "examples/provider/event_task_runner.h" #include <signal.h>
diff --git a/libweave/examples/ubuntu/event_task_runner.h b/libweave/examples/provider/event_task_runner.h similarity index 90% rename from libweave/examples/ubuntu/event_task_runner.h rename to libweave/examples/provider/event_task_runner.h index 77d7e72..473441e 100644 --- a/libweave/examples/ubuntu/event_task_runner.h +++ b/libweave/examples/provider/event_task_runner.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_EVENT_TASK_RUNNER_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_EVENT_TASK_RUNNER_H_ +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_EVENT_TASK_RUNNER_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_EVENT_TASK_RUNNER_H_ #include <queue> #include <utility> @@ -56,4 +56,4 @@ } // namespace examples } // namespace weave -#endif // LIBWEAVE_EXAMPLES_UBUNTU_EVENT_TASK_RUNNER_H_ +#endif // LIBWEAVE_EXAMPLES_PROVIDER_EVENT_TASK_RUNNER_H_
diff --git a/libweave/examples/ubuntu/file_config_store.cc b/libweave/examples/provider/file_config_store.cc similarity index 97% rename from libweave/examples/ubuntu/file_config_store.cc rename to libweave/examples/provider/file_config_store.cc index d3f10ef..44f2c30 100644 --- a/libweave/examples/ubuntu/file_config_store.cc +++ b/libweave/examples/provider/file_config_store.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "examples/ubuntu/file_config_store.h" +#include "examples/provider/file_config_store.h" #include <sys/stat.h> #include <sys/utsname.h>
diff --git a/libweave/examples/ubuntu/file_config_store.h b/libweave/examples/provider/file_config_store.h similarity index 79% rename from libweave/examples/ubuntu/file_config_store.h rename to libweave/examples/provider/file_config_store.h index 1f3d181..e4d16a9 100644 --- a/libweave/examples/ubuntu/file_config_store.h +++ b/libweave/examples/provider/file_config_store.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_FILE_CONFIG_STORE_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_FILE_CONFIG_STORE_H_ +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_FILE_CONFIG_STORE_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_FILE_CONFIG_STORE_H_ #include <map> #include <string> @@ -29,4 +29,4 @@ } // namespace examples } // namespace weave -#endif // LIBWEAVE_EXAMPLES_UBUNTU_FILE_CONFIG_STORE_H_ +#endif // LIBWEAVE_EXAMPLES_PROVIDER_FILE_CONFIG_STORE_H_
diff --git a/libweave/examples/provider/provider.gyp b/libweave/examples/provider/provider.gyp new file mode 100644 index 0000000..9dcf184 --- /dev/null +++ b/libweave/examples/provider/provider.gyp
@@ -0,0 +1,59 @@ +# 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. +{ + 'targets': [ + { + 'target_name': 'libweave_provider', + 'type': 'static_library', + 'variables': { + 'deps': [ + 'avahi-client', + 'expat', + 'libcurl', + 'libcrypto', + 'openssl', + ] + }, + 'cflags': [ + '>!@(pkg-config >(deps) --cflags)', + '-pthread', + ], + 'sources': [ + 'avahi_client.cc', + 'bluez_client.cc', + 'curl_http_client.cc', + 'event_http_client.cc', + 'event_http_server.cc', + 'event_network.cc', + 'event_task_runner.cc', + 'file_config_store.cc', + 'wifi_manager.cc', + 'ssl_stream.cc', + ], + 'dependencies': [ + '../../libweave_standalone.gyp:libweave', + ], + 'direct_dependent_settings' : { + 'variables': { + 'parent_deps': [ + '<@(deps)' + ] + }, + 'link_settings': { + 'ldflags+': [ + '>!@(pkg-config >(parent_deps) --libs-only-L --libs-only-other)', + ], + 'libraries+': [ + '>!(pkg-config >(parent_deps) --libs-only-l)', + ], + }, + 'libraries': [ + '-levent', + '-levent_openssl', + '-lpthread', + ] + } + } + ] +}
diff --git a/libweave/examples/provider/ssl_stream.cc b/libweave/examples/provider/ssl_stream.cc new file mode 100644 index 0000000..eea28c0 --- /dev/null +++ b/libweave/examples/provider/ssl_stream.cc
@@ -0,0 +1,207 @@ +// 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 "examples/provider/ssl_stream.h" + +#include <openssl/err.h> + +#include <base/bind.h> +#include <base/bind_helpers.h> +#include <weave/provider/task_runner.h> + +namespace weave { +namespace examples { + +namespace { + +void AddSslError(ErrorPtr* error, + const tracked_objects::Location& location, + const std::string& error_code, + unsigned long ssl_error_code) { + ERR_load_BIO_strings(); + SSL_load_error_strings(); + Error::AddToPrintf(error, location, "ssl_stream", error_code, "%s: %s", + ERR_lib_error_string(ssl_error_code), + ERR_reason_error_string(ssl_error_code)); +} + +void RetryAsyncTask(provider::TaskRunner* task_runner, + const tracked_objects::Location& location, + const base::Closure& task) { + task_runner->PostDelayedTask(FROM_HERE, task, + base::TimeDelta::FromMilliseconds(100)); +} + +} // namespace + +void SSLStream::SslDeleter::operator()(BIO* bio) const { + BIO_free(bio); +} + +void SSLStream::SslDeleter::operator()(SSL* ssl) const { + SSL_free(ssl); +} + +void SSLStream::SslDeleter::operator()(SSL_CTX* ctx) const { + SSL_CTX_free(ctx); +} + +SSLStream::SSLStream(provider::TaskRunner* task_runner, + std::unique_ptr<BIO, SslDeleter> stream_bio) + : task_runner_{task_runner} { + ctx_.reset(SSL_CTX_new(TLSv1_2_client_method())); + CHECK(ctx_); + ssl_.reset(SSL_new(ctx_.get())); + + SSL_set_bio(ssl_.get(), stream_bio.get(), stream_bio.get()); + stream_bio.release(); // Owned by ssl now. + SSL_set_connect_state(ssl_.get()); +} + +SSLStream::~SSLStream() { + CancelPendingOperations(); +} + +void SSLStream::RunTask(const base::Closure& task) { + task.Run(); +} + +void SSLStream::Read(void* buffer, + size_t size_to_read, + const ReadCallback& callback) { + int res = SSL_read(ssl_.get(), buffer, size_to_read); + if (res > 0) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::RunTask, weak_ptr_factory_.GetWeakPtr(), + base::Bind(callback, res, nullptr)), + {}); + return; + } + + int err = SSL_get_error(ssl_.get(), res); + + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + return RetryAsyncTask( + task_runner_, FROM_HERE, + base::Bind(&SSLStream::Read, weak_ptr_factory_.GetWeakPtr(), buffer, + size_to_read, callback)); + } + + ErrorPtr weave_error; + AddSslError(&weave_error, FROM_HERE, "read_failed", err); + return task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::RunTask, weak_ptr_factory_.GetWeakPtr(), + base::Bind(callback, 0, base::Passed(&weave_error))), + {}); +} + +void SSLStream::Write(const void* buffer, + size_t size_to_write, + const WriteCallback& callback) { + int res = SSL_write(ssl_.get(), buffer, size_to_write); + if (res > 0) { + buffer = static_cast<const char*>(buffer) + res; + size_to_write -= res; + if (size_to_write == 0) { + return task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&SSLStream::RunTask, weak_ptr_factory_.GetWeakPtr(), + base::Bind(callback, nullptr)), + {}); + } + + return RetryAsyncTask( + task_runner_, FROM_HERE, + base::Bind(&SSLStream::Write, weak_ptr_factory_.GetWeakPtr(), buffer, + size_to_write, callback)); + } + + int err = SSL_get_error(ssl_.get(), res); + + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + return RetryAsyncTask( + task_runner_, FROM_HERE, + base::Bind(&SSLStream::Write, weak_ptr_factory_.GetWeakPtr(), buffer, + size_to_write, callback)); + } + + ErrorPtr weave_error; + AddSslError(&weave_error, FROM_HERE, "write_failed", err); + task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(&SSLStream::RunTask, weak_ptr_factory_.GetWeakPtr(), + base::Bind(callback, base::Passed(&weave_error))), + {}); +} + +void SSLStream::CancelPendingOperations() { + weak_ptr_factory_.InvalidateWeakPtrs(); +} + +void SSLStream::Connect( + provider::TaskRunner* task_runner, + const std::string& host, + uint16_t port, + const provider::Network::OpenSslSocketCallback& callback) { + SSL_library_init(); + + char end_point[255]; + snprintf(end_point, sizeof(end_point), "%s:%u", host.c_str(), port); + + std::unique_ptr<BIO, SslDeleter> stream_bio(BIO_new_connect(end_point)); + CHECK(stream_bio); + BIO_set_nbio(stream_bio.get(), 1); + + std::unique_ptr<SSLStream> stream{ + new SSLStream{task_runner, std::move(stream_bio)}}; + ConnectBio(std::move(stream), callback); +} + +void SSLStream::ConnectBio( + std::unique_ptr<SSLStream> stream, + const provider::Network::OpenSslSocketCallback& callback) { + BIO* bio = SSL_get_rbio(stream->ssl_.get()); + if (BIO_do_connect(bio) == 1) + return DoHandshake(std::move(stream), callback); + + auto task_runner = stream->task_runner_; + if (BIO_should_retry(bio)) { + return RetryAsyncTask( + task_runner, FROM_HERE, + base::Bind(&SSLStream::ConnectBio, base::Passed(&stream), callback)); + } + + ErrorPtr error; + AddSslError(&error, FROM_HERE, "connect_failed", ERR_get_error()); + task_runner->PostDelayedTask( + FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)), {}); +} + +void SSLStream::DoHandshake( + std::unique_ptr<SSLStream> stream, + const provider::Network::OpenSslSocketCallback& callback) { + int res = SSL_do_handshake(stream->ssl_.get()); + auto task_runner = stream->task_runner_; + if (res == 1) { + return task_runner->PostDelayedTask( + FROM_HERE, base::Bind(callback, base::Passed(&stream), nullptr), {}); + } + + res = SSL_get_error(stream->ssl_.get(), res); + + if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) { + return RetryAsyncTask( + task_runner, FROM_HERE, + base::Bind(&SSLStream::DoHandshake, base::Passed(&stream), callback)); + } + + ErrorPtr error; + AddSslError(&error, FROM_HERE, "handshake_failed", res); + task_runner->PostDelayedTask( + FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)), {}); +} + +} // namespace examples +} // namespace weave
diff --git a/libweave/examples/provider/ssl_stream.h b/libweave/examples/provider/ssl_stream.h new file mode 100644 index 0000000..f1ef4a6 --- /dev/null +++ b/libweave/examples/provider/ssl_stream.h
@@ -0,0 +1,72 @@ +// 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. + +#ifndef LIBWEAVE_EXAMPLES_PROVIDER_SSL_STREAM_H_ +#define LIBWEAVE_EXAMPLES_PROVIDER_SSL_STREAM_H_ + +#include <openssl/ssl.h> + +#include <base/memory/weak_ptr.h> +#include <weave/provider/network.h> +#include <weave/stream.h> + +namespace weave { + +namespace provider { +class TaskRunner; +} + +namespace examples { + +class SSLStream : public Stream { + public: + ~SSLStream() override; + + void Read(void* buffer, + size_t size_to_read, + const ReadCallback& callback) override; + + void Write(const void* buffer, + size_t size_to_write, + const WriteCallback& callback) override; + + void CancelPendingOperations() override; + + static void Connect(provider::TaskRunner* task_runner, + const std::string& host, + uint16_t port, + const provider::Network::OpenSslSocketCallback& callback); + + private: + struct SslDeleter { + void operator()(BIO* bio) const; + void operator()(SSL* ssl) const; + void operator()(SSL_CTX* ctx) const; + }; + + SSLStream(provider::TaskRunner* task_runner, + std::unique_ptr<BIO, SslDeleter> stream_bio); + + static void ConnectBio( + std::unique_ptr<SSLStream> stream, + const provider::Network::OpenSslSocketCallback& callback); + static void DoHandshake( + std::unique_ptr<SSLStream> stream, + const provider::Network::OpenSslSocketCallback& callback); + + // Send task to this method with WeakPtr if callback should not be executed + // after SSLStream is destroyed. + void RunTask(const base::Closure& task); + + provider::TaskRunner* task_runner_{nullptr}; + std::unique_ptr<SSL_CTX, SslDeleter> ctx_; + std::unique_ptr<SSL, SslDeleter> ssl_; + + base::WeakPtrFactory<SSLStream> weak_ptr_factory_{this}; +}; + +} // namespace examples +} // namespace weave + +#endif // LIBWEAVE_EXAMPLES_PROVIDER_SSL_STREAM_H_
diff --git a/libweave/examples/provider/wifi_manager.cc b/libweave/examples/provider/wifi_manager.cc new file mode 100644 index 0000000..ac1c604 --- /dev/null +++ b/libweave/examples/provider/wifi_manager.cc
@@ -0,0 +1,167 @@ +// 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 "examples/provider/wifi_manager.h" + +#include <arpa/inet.h> +#include <linux/wireless.h> +#include <sys/ioctl.h> +#include <sys/wait.h> + +#include <fstream> + +#include <base/bind.h> +#include <weave/provider/task_runner.h> + +#include "examples/provider/ssl_stream.h" + +namespace weave { +namespace examples { + +namespace { + +int ForkCmd(const std::string& path, const std::vector<std::string>& args) { + int pid = fork(); + if (pid != 0) + return pid; + + std::vector<const char*> args_vector; + args_vector.push_back(path.c_str()); + for (auto& i : args) + args_vector.push_back(i.c_str()); + args_vector.push_back(nullptr); + + execvp(path.c_str(), const_cast<char**>(args_vector.data())); + NOTREACHED(); + return 0; +} + +} // namespace + +WifiImpl::WifiImpl(provider::TaskRunner* task_runner, bool force_bootstrapping) + : force_bootstrapping_{force_bootstrapping}, task_runner_{task_runner} { + StopAccessPoint(); +} +WifiImpl::~WifiImpl() { + StopAccessPoint(); +} + +void WifiImpl::TryToConnect(const std::string& ssid, + const std::string& passphrase, + int pid, + base::Time until, + const DoneCallback& callback) { + if (pid) { + int status = 0; + if (pid == waitpid(pid, &status, WNOWAIT)) { + int sockf_d = socket(AF_INET, SOCK_DGRAM, 0); + CHECK_GE(sockf_d, 0) << strerror(errno); + + iwreq wreq = {}; + snprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "wlan0"); + std::string essid(' ', IW_ESSID_MAX_SIZE + 1); + wreq.u.essid.pointer = &essid[0]; + wreq.u.essid.length = essid.size(); + CHECK_GE(ioctl(sockf_d, SIOCGIWESSID, &wreq), 0) << strerror(errno); + essid.resize(wreq.u.essid.length); + close(sockf_d); + + if (ssid == essid) + return task_runner_->PostDelayedTask(FROM_HERE, + base::Bind(callback, nullptr), {}); + pid = 0; // Try again. + } + } + + if (pid == 0) { + pid = ForkCmd("nmcli", + {"dev", "wifi", "connect", ssid, "password", passphrase}); + } + + if (base::Time::Now() >= until) { + ErrorPtr error; + Error::AddTo(&error, FROM_HERE, "wifi", "timeout", + "Timeout connecting to WiFI network."); + task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(callback, base::Passed(&error)), {}); + return; + } + + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&WifiImpl::TryToConnect, weak_ptr_factory_.GetWeakPtr(), ssid, + passphrase, pid, until, callback), + base::TimeDelta::FromSeconds(1)); +} + +void WifiImpl::Connect(const std::string& ssid, + const std::string& passphrase, + const DoneCallback& callback) { + force_bootstrapping_ = false; + CHECK(!hostapd_started_); + if (hostapd_started_) { + ErrorPtr error; + Error::AddTo(&error, FROM_HERE, "wifi", "busy", "Running Access Point."); + task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(callback, base::Passed(&error)), {}); + return; + } + + TryToConnect(ssid, passphrase, 0, + base::Time::Now() + base::TimeDelta::FromMinutes(1), callback); +} + +void WifiImpl::StartAccessPoint(const std::string& ssid) { + if (hostapd_started_) + return; + + // Release wlan0 interface. + CHECK_EQ(0, std::system("nmcli nm wifi off")); + CHECK_EQ(0, std::system("rfkill unblock wlan")); + sleep(1); + + std::string hostapd_conf = "/tmp/weave_hostapd.conf"; + { + std::ofstream ofs(hostapd_conf); + ofs << "interface=wlan0" << std::endl; + ofs << "channel=1" << std::endl; + ofs << "ssid=" << ssid << std::endl; + } + + CHECK_EQ(0, std::system(("hostapd -B -K " + hostapd_conf).c_str())); + hostapd_started_ = true; + + for (size_t i = 0; i < 10; ++i) { + if (0 == std::system("ifconfig wlan0 192.168.76.1/24")) + break; + sleep(1); + } + + std::string dnsmasq_conf = "/tmp/weave_dnsmasq.conf"; + { + std::ofstream ofs(dnsmasq_conf.c_str()); + ofs << "port=0" << std::endl; + ofs << "bind-interfaces" << std::endl; + ofs << "log-dhcp" << std::endl; + ofs << "dhcp-range=192.168.76.10,192.168.76.100" << std::endl; + ofs << "interface=wlan0" << std::endl; + ofs << "dhcp-leasefile=" << dnsmasq_conf << ".leases" << std::endl; + } + + CHECK_EQ(0, std::system(("dnsmasq --conf-file=" + dnsmasq_conf).c_str())); +} + +void WifiImpl::StopAccessPoint() { + base::IgnoreResult(std::system("pkill -f dnsmasq.*/tmp/weave")); + base::IgnoreResult(std::system("pkill -f hostapd.*/tmp/weave")); + CHECK_EQ(0, std::system("nmcli nm wifi on")); + hostapd_started_ = false; +} + +bool WifiImpl::HasWifiCapability() { + return std::system("nmcli dev | grep ^wlan0") == 0; +} + +} // namespace examples +} // namespace weave
diff --git a/libweave/examples/provider/wifi_manager.h b/libweave/examples/provider/wifi_manager.h new file mode 100644 index 0000000..849beef --- /dev/null +++ b/libweave/examples/provider/wifi_manager.h
@@ -0,0 +1,55 @@ +// 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. + +#ifndef LIBWEAVE_EXAMPLES_UBUNTU_WIFI_MANAGER_H_ +#define LIBWEAVE_EXAMPLES_UBUNTU_WIFI_MANAGER_H_ + +#include <string> +#include <vector> + +#include <base/memory/weak_ptr.h> +#include <base/time/time.h> +#include <weave/provider/wifi.h> + +namespace weave { + +namespace provider { +class TaskRunner; +} + +namespace examples { + +// Basic weave::Wifi implementation. +// Production version of SSL socket needs secure server certificate check. +class WifiImpl : public provider::Wifi { + public: + explicit WifiImpl(provider::TaskRunner* task_runner, + bool force_bootstrapping); + ~WifiImpl(); + + // Wifi implementation. + void Connect(const std::string& ssid, + const std::string& passphrase, + const DoneCallback& callback) override; + void StartAccessPoint(const std::string& ssid) override; + void StopAccessPoint() override; + + static bool HasWifiCapability(); + + private: + void TryToConnect(const std::string& ssid, + const std::string& passphrase, + int pid, + base::Time until, + const DoneCallback& callback); + bool force_bootstrapping_{false}; + bool hostapd_started_{false}; + provider::TaskRunner* task_runner_{nullptr}; + base::WeakPtrFactory<WifiImpl> weak_ptr_factory_{this}; +}; + +} // namespace examples +} // namespace weave + +#endif // LIBWEAVE_EXAMPLES_UBUNTU_WIFI_MANAGER_H_
diff --git a/libweave/examples/ubuntu/main.cc b/libweave/examples/ubuntu/main.cc deleted file mode 100644 index cd6dc06..0000000 --- a/libweave/examples/ubuntu/main.cc +++ /dev/null
@@ -1,290 +0,0 @@ -// 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 <bitset> - -#include <base/bind.h> -#include <base/values.h> -#include <weave/device.h> -#include <weave/error.h> - -#include "examples/ubuntu/avahi_client.h" -#include "examples/ubuntu/bluez_client.h" -#include "examples/ubuntu/curl_http_client.h" -#include "examples/ubuntu/event_http_server.h" -#include "examples/ubuntu/event_task_runner.h" -#include "examples/ubuntu/file_config_store.h" -#include "examples/ubuntu/network_manager.h" - -namespace { - -// Supported LED count on this device -const size_t kLedCount = 3; - -void ShowUsage(const std::string& name) { - LOG(ERROR) << "\nUsage: " << name << " <option(s)>" - << "\nOptions:\n" - << "\t-h,--help Show this help message\n" - << "\t--v=LEVEL Logging level\n" - << "\t-b,--bootstrapping Force WiFi bootstrapping\n" - << "\t-d,--disable_security Disable privet security\n" - << "\t--registration_ticket=TICKET Register device with the " - "given ticket\n"; -} - -class CommandHandler { - public: - CommandHandler(weave::Device* device, - weave::provider::TaskRunner* task_runner) - : device_{device}, task_runner_(task_runner) { - device->AddStateDefinitionsFromJson(R"({ - "_greeter": {"_greetings_counter":"integer"}, - "_ledflasher": {"_leds": {"items": "boolean"}} - })"); - - device->SetStatePropertiesFromJson(R"({ - "_greeter": {"_greetings_counter": 0}, - "_ledflasher":{"_leds": [false, false, false]} - })", - nullptr); - - device->AddCommandDefinitionsFromJson(R"({ - "_greeter": { - "_greet": { - "minimalRole": "user", - "parameters": { - "_name": "string", - "_count": {"minimum": 1, "maximum": 100} - }, - "progress": { "_todo": "integer"}, - "results": { "_greeting": "string" } - } - }, - "_ledflasher": { - "_set":{ - "parameters": { - "_led": {"minimum": 1, "maximum": 3}, - "_on": "boolean" - } - }, - "_toggle":{ - "parameters": { - "_led": {"minimum": 1, "maximum": 3} - } - } - } - })"); - device->AddCommandHandler( - "_ledflasher._toggle", - base::Bind(&CommandHandler::OnFlasherToggleCommand, - weak_ptr_factory_.GetWeakPtr())); - device->AddCommandHandler("_greeter._greet", - base::Bind(&CommandHandler::OnGreetCommand, - weak_ptr_factory_.GetWeakPtr())); - device->AddCommandHandler("_ledflasher._set", - base::Bind(&CommandHandler::OnFlasherSetCommand, - weak_ptr_factory_.GetWeakPtr())); - device->AddCommandHandler("", - base::Bind(&CommandHandler::OnUnhandledCommand, - weak_ptr_factory_.GetWeakPtr())); - } - - private: - void DoGreet(const std::weak_ptr<weave::Command>& command, int todo) { - auto cmd = command.lock(); - if (!cmd) - return; - - std::string name; - if (!cmd->GetParameters()->GetString("_name", &name)) { - weave::ErrorPtr error; - weave::Error::AddTo(&error, FROM_HERE, "example", - "invalid_parameter_value", "Name is missing"); - cmd->Abort(error.get(), nullptr); - return; - } - - if (todo-- > 0) { - LOG(INFO) << "Hello " << name; - - base::DictionaryValue progress; - progress.SetInteger("_todo", todo); - cmd->SetProgress(progress, nullptr); - - base::DictionaryValue state; - state.SetInteger("_greeter._greetings_counter", ++counter_); - device_->SetStateProperties(state, nullptr); - } - - if (todo > 0) { - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&CommandHandler::DoGreet, - weak_ptr_factory_.GetWeakPtr(), command, todo), - base::TimeDelta::FromSeconds(1)); - return; - } - - base::DictionaryValue result; - result.SetString("_greeting", "Hello " + name); - cmd->Complete(result, nullptr); - LOG(INFO) << cmd->GetName() << " command finished: " << result; - LOG(INFO) << "New state: " << *device_->GetState(); - } - - void OnGreetCommand(const std::weak_ptr<weave::Command>& command) { - auto cmd = command.lock(); - if (!cmd) - return; - LOG(INFO) << "received command: " << cmd->GetName(); - - int todo = 1; - cmd->GetParameters()->GetInteger("_count", &todo); - DoGreet(command, todo); - } - - void OnFlasherSetCommand(const std::weak_ptr<weave::Command>& command) { - auto cmd = command.lock(); - if (!cmd) - return; - LOG(INFO) << "received command: " << cmd->GetName(); - int32_t led_index = 0; - bool cmd_value = false; - if (cmd->GetParameters()->GetInteger("_led", &led_index) && - cmd->GetParameters()->GetBoolean("_on", &cmd_value)) { - // Display this command in terminal - LOG(INFO) << cmd->GetName() << " _led: " << led_index - << ", _on: " << (cmd_value ? "true" : "false"); - - led_index--; - int new_state = cmd_value ? 1 : 0; - int cur_state = led_status_[led_index]; - led_status_[led_index] = new_state; - - if (cmd_value != cur_state) { - UpdateLedState(); - } - cmd->Complete({}, nullptr); - return; - } - weave::ErrorPtr error; - weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value", - "Invalid parameters"); - cmd->Abort(error.get(), nullptr); - } - - void OnFlasherToggleCommand(const std::weak_ptr<weave::Command>& command) { - auto cmd = command.lock(); - if (!cmd) - return; - LOG(INFO) << "received command: " << cmd->GetName(); - int32_t led_index = 0; - if (cmd->GetParameters()->GetInteger("_led", &led_index)) { - LOG(INFO) << cmd->GetName() << " _led: " << led_index; - led_index--; - led_status_[led_index] = ~led_status_[led_index]; - - UpdateLedState(); - cmd->Complete({}, nullptr); - return; - } - weave::ErrorPtr error; - weave::Error::AddTo(&error, FROM_HERE, "example", "invalid_parameter_value", - "Invalid parameters"); - cmd->Abort(error.get(), nullptr); - } - - void OnUnhandledCommand(const std::weak_ptr<weave::Command>& command) { - auto cmd = command.lock(); - if (!cmd) - return; - LOG(INFO) << cmd->GetName() << " unimplemented command: ignored"; - } - - void UpdateLedState(void) { - base::ListValue list; - for (uint32_t i = 0; i < led_status_.size(); i++) - list.AppendBoolean(led_status_[i] ? true : false); - - device_->SetStateProperty("_ledflasher._leds", list, nullptr); - } - - weave::Device* device_{nullptr}; - weave::provider::TaskRunner* task_runner_{nullptr}; - - int counter_{0}; - - // Simulate LED status on this device so client app could explore - // Each bit represents one device, indexing from LSB - std::bitset<kLedCount> led_status_{0}; - - base::WeakPtrFactory<CommandHandler> weak_ptr_factory_{this}; -}; - -void OnRegisterDeviceDone(weave::Device* device, weave::ErrorPtr error) { - if (error) - LOG(ERROR) << "Fail to register device: " << error->GetMessage(); - else - LOG(INFO) << "Device registered: " << device->GetSettings().cloud_id; -} - -} // namespace - -int main(int argc, char** argv) { - bool force_bootstrapping = false; - bool disable_security = false; - std::string registration_ticket; - for (int i = 1; i < argc; ++i) { - std::string arg = argv[i]; - if (arg == "-h" || arg == "--help") { - ShowUsage(argv[0]); - return 0; - } else if (arg == "-b" || arg == "--bootstrapping") { - force_bootstrapping = true; - } else if (arg == "-d" || arg == "--disable_security") { - disable_security = true; - } else if (arg.find("--registration_ticket") != std::string::npos) { - auto pos = arg.find("="); - if (pos == std::string::npos) { - ShowUsage(argv[0]); - return 1; - } - registration_ticket = arg.substr(pos + 1); - } else if (arg.find("--v") != std::string::npos) { - auto pos = arg.find("="); - if (pos == std::string::npos) { - ShowUsage(argv[0]); - return 1; - } - logging::SetMinLogLevel(-std::stoi(arg.substr(pos + 1))); - } else { - ShowUsage(argv[0]); - return 1; - } - } - - weave::examples::FileConfigStore config_store{disable_security}; - weave::examples::EventTaskRunner task_runner; - weave::examples::CurlHttpClient http_client{&task_runner}; - weave::examples::NetworkImpl network{&task_runner, force_bootstrapping}; - weave::examples::AvahiClient dns_sd; - weave::examples::HttpServerImpl http_server{&task_runner}; - weave::examples::BluetoothImpl bluetooth; - - auto device = weave::Device::Create( - &config_store, &task_runner, &http_client, &network, &dns_sd, - &http_server, - weave::examples::NetworkImpl::HasWifiCapability() ? &network : nullptr, - &bluetooth); - - if (!registration_ticket.empty()) { - device->Register(registration_ticket, - base::Bind(&OnRegisterDeviceDone, device.get())); - } - - CommandHandler handler(device.get(), &task_runner); - task_runner.Run(); - - LOG(INFO) << "exit"; - return 0; -}
diff --git a/libweave/examples/ubuntu/network_manager.cc b/libweave/examples/ubuntu/network_manager.cc deleted file mode 100644 index efc2d5c..0000000 --- a/libweave/examples/ubuntu/network_manager.cc +++ /dev/null
@@ -1,221 +0,0 @@ -// 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 "examples/ubuntu/network_manager.h" - -#include <arpa/inet.h> -#include <linux/wireless.h> -#include <sys/ioctl.h> -#include <sys/wait.h> - -#include <fstream> - -#include <base/bind.h> -#include <weave/provider/task_runner.h> - -#include "examples/ubuntu/ssl_stream.h" - -namespace weave { -namespace examples { - -namespace { - -int ForkCmd(const std::string& path, const std::vector<std::string>& args) { - int pid = fork(); - if (pid != 0) - return pid; - - std::vector<const char*> args_vector; - args_vector.push_back(path.c_str()); - for (auto& i : args) - args_vector.push_back(i.c_str()); - args_vector.push_back(nullptr); - - execvp(path.c_str(), const_cast<char**>(args_vector.data())); - NOTREACHED(); - return 0; -} - -} // namespace - -NetworkImpl::NetworkImpl(provider::TaskRunner* task_runner, - bool force_bootstrapping) - : force_bootstrapping_{force_bootstrapping}, task_runner_{task_runner} { - SSL_load_error_strings(); - SSL_library_init(); - - StopAccessPoint(); - UpdateNetworkState(); -} -NetworkImpl::~NetworkImpl() { - StopAccessPoint(); -} - -void NetworkImpl::AddConnectionChangedCallback( - const ConnectionChangedCallback& callback) { - callbacks_.push_back(callback); -} - -void NetworkImpl::TryToConnect(const std::string& ssid, - const std::string& passphrase, - int pid, - base::Time until, - const DoneCallback& callback) { - if (pid) { - int status = 0; - if (pid == waitpid(pid, &status, WNOWAIT)) { - int sockf_d = socket(AF_INET, SOCK_DGRAM, 0); - CHECK_GE(sockf_d, 0) << strerror(errno); - - iwreq wreq = {}; - snprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "wlan0"); - std::string essid(' ', IW_ESSID_MAX_SIZE + 1); - wreq.u.essid.pointer = &essid[0]; - wreq.u.essid.length = essid.size(); - CHECK_GE(ioctl(sockf_d, SIOCGIWESSID, &wreq), 0) << strerror(errno); - essid.resize(wreq.u.essid.length); - close(sockf_d); - - if (ssid == essid) - return task_runner_->PostDelayedTask(FROM_HERE, - base::Bind(callback, nullptr), {}); - pid = 0; // Try again. - } - } - - if (pid == 0) { - pid = ForkCmd("nmcli", - {"dev", "wifi", "connect", ssid, "password", passphrase}); - } - - if (base::Time::Now() >= until) { - ErrorPtr error; - Error::AddTo(&error, FROM_HERE, "wifi", "timeout", - "Timeout connecting to WiFI network."); - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, base::Passed(&error)), {}); - return; - } - - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&NetworkImpl::TryToConnect, weak_ptr_factory_.GetWeakPtr(), - ssid, passphrase, pid, until, callback), - base::TimeDelta::FromSeconds(1)); -} - -void NetworkImpl::Connect(const std::string& ssid, - const std::string& passphrase, - const DoneCallback& callback) { - force_bootstrapping_ = false; - CHECK(!hostapd_started_); - if (hostapd_started_) { - ErrorPtr error; - Error::AddTo(&error, FROM_HERE, "wifi", "busy", "Running Access Point."); - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, base::Passed(&error)), {}); - return; - } - - TryToConnect(ssid, passphrase, 0, - base::Time::Now() + base::TimeDelta::FromMinutes(1), callback); -} - -void NetworkImpl::UpdateNetworkState() { - network_state_ = Network::State::kOffline; - if (force_bootstrapping_) - return; - if (std::system("ping talk.google.com -c 1") == 0) - network_state_ = State::kOnline; - else if (std::system("nmcli dev")) - network_state_ = State::kError; - else if (std::system("nmcli dev | grep connecting") == 0) - network_state_ = State::kConnecting; - - task_runner_->PostDelayedTask(FROM_HERE, - base::Bind(&NetworkImpl::UpdateNetworkState, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromSeconds(10)); - for (const auto& cb : callbacks_) - cb.Run(); -} - -provider::Network::State NetworkImpl::GetConnectionState() const { - return network_state_; -} - -void NetworkImpl::StartAccessPoint(const std::string& ssid) { - if (hostapd_started_) - return; - - network_state_ = State::kOffline; - - // Release wlan0 interface. - CHECK_EQ(0, std::system("nmcli nm wifi off")); - CHECK_EQ(0, std::system("rfkill unblock wlan")); - sleep(1); - - std::string hostapd_conf = "/tmp/weave_hostapd.conf"; - { - std::ofstream ofs(hostapd_conf); - ofs << "interface=wlan0" << std::endl; - ofs << "channel=1" << std::endl; - ofs << "ssid=" << ssid << std::endl; - } - - CHECK_EQ(0, std::system(("hostapd -B -K " + hostapd_conf).c_str())); - hostapd_started_ = true; - - for (size_t i = 0; i < 10; ++i) { - if (0 == std::system("ifconfig wlan0 192.168.76.1/24")) - break; - sleep(1); - } - - std::string dnsmasq_conf = "/tmp/weave_dnsmasq.conf"; - { - std::ofstream ofs(dnsmasq_conf.c_str()); - ofs << "port=0" << std::endl; - ofs << "bind-interfaces" << std::endl; - ofs << "log-dhcp" << std::endl; - ofs << "dhcp-range=192.168.76.10,192.168.76.100" << std::endl; - ofs << "interface=wlan0" << std::endl; - ofs << "dhcp-leasefile=" << dnsmasq_conf << ".leases" << std::endl; - } - - CHECK_EQ(0, std::system(("dnsmasq --conf-file=" + dnsmasq_conf).c_str())); -} - -void NetworkImpl::StopAccessPoint() { - base::IgnoreResult(std::system("pkill -f dnsmasq.*/tmp/weave")); - base::IgnoreResult(std::system("pkill -f hostapd.*/tmp/weave")); - CHECK_EQ(0, std::system("nmcli nm wifi on")); - hostapd_started_ = false; -} - -bool NetworkImpl::HasWifiCapability() { - return std::system("nmcli dev | grep ^wlan0") == 0; -} - -void NetworkImpl::OpenSslSocket(const std::string& host, - uint16_t port, - const OpenSslSocketCallback& callback) { - // Connect to SSL port instead of upgrading to TLS. - std::unique_ptr<SSLStream> tls_stream{new SSLStream{task_runner_}}; - - if (tls_stream->Init(host, port)) { - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, base::Passed(&tls_stream), nullptr), - {}); - } else { - ErrorPtr error; - Error::AddTo(&error, FROM_HERE, "tls", "tls_init_failed", - "Failed to initialize TLS stream."); - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)), {}); - } -} - -} // namespace examples -} // namespace weave
diff --git a/libweave/examples/ubuntu/network_manager.h b/libweave/examples/ubuntu/network_manager.h deleted file mode 100644 index 3769ab1..0000000 --- a/libweave/examples/ubuntu/network_manager.h +++ /dev/null
@@ -1,69 +0,0 @@ -// 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. - -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_NETWORK_MANAGER_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_NETWORK_MANAGER_H_ - -#include <string> -#include <vector> - -#include <base/memory/weak_ptr.h> -#include <base/time/time.h> -#include <weave/provider/network.h> -#include <weave/provider/wifi.h> - -namespace weave { - -namespace provider { -class TaskRunner; -} - -namespace examples { - -// Basic weave::Network implementation. -// Production version of SSL socket needs secure server certificate check. -class NetworkImpl : public provider::Network, public provider::Wifi { - public: - explicit NetworkImpl(provider::TaskRunner* task_runner, - bool force_bootstrapping); - ~NetworkImpl(); - - // Network implementation. - void AddConnectionChangedCallback( - const ConnectionChangedCallback& callback) override; - State GetConnectionState() const override; - void OpenSslSocket(const std::string& host, - uint16_t port, - const OpenSslSocketCallback& callback) override; - - // Wifi implementation. - void Connect(const std::string& ssid, - const std::string& passphrase, - const DoneCallback& callback) override; - void StartAccessPoint(const std::string& ssid) override; - void StopAccessPoint() override; - - static bool HasWifiCapability(); - - private: - void TryToConnect(const std::string& ssid, - const std::string& passphrase, - int pid, - base::Time until, - const DoneCallback& callback); - void UpdateNetworkState(); - - bool force_bootstrapping_{false}; - bool hostapd_started_{false}; - provider::TaskRunner* task_runner_{nullptr}; - std::vector<ConnectionChangedCallback> callbacks_; - provider::Network::State network_state_{provider::Network::State::kOffline}; - - base::WeakPtrFactory<NetworkImpl> weak_ptr_factory_{this}; -}; - -} // namespace examples -} // namespace weave - -#endif // LIBWEAVE_EXAMPLES_UBUNTU_NETWORK_MANAGER_H_
diff --git a/libweave/examples/ubuntu/ssl_stream.cc b/libweave/examples/ubuntu/ssl_stream.cc deleted file mode 100644 index fc2d36d..0000000 --- a/libweave/examples/ubuntu/ssl_stream.cc +++ /dev/null
@@ -1,144 +0,0 @@ -// 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 "examples/ubuntu/ssl_stream.h" - -#include <base/bind.h> -#include <weave/provider/task_runner.h> - -namespace weave { -namespace examples { - -SSLStream::SSLStream(provider::TaskRunner* task_runner) - : task_runner_{task_runner} {} - -SSLStream::~SSLStream() { - CancelPendingOperations(); -} - -void SSLStream::RunDelayedTask(const base::Closure& task) { - task.Run(); -} - -void SSLStream::Read(void* buffer, - size_t size_to_read, - const ReadCallback& callback) { - int res = SSL_read(ssl_.get(), buffer, size_to_read); - if (res > 0) { - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), - base::Bind(callback, res, nullptr)), - {}); - return; - } - - int err = SSL_get_error(ssl_.get(), res); - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&SSLStream::Read, weak_ptr_factory_.GetWeakPtr(), - buffer, size_to_read, callback), - base::TimeDelta::FromSeconds(1)); - return; - } - - ErrorPtr weave_error; - Error::AddTo(&weave_error, FROM_HERE, "ssl", "socket_read_failed", - "SSL error"); - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), - base::Bind(callback, 0, base::Passed(&weave_error))), - {}); - return; -} - -void SSLStream::Write(const void* buffer, - size_t size_to_write, - const WriteCallback& callback) { - int res = SSL_write(ssl_.get(), buffer, size_to_write); - if (res > 0) { - buffer = static_cast<const char*>(buffer) + res; - size_to_write -= res; - if (size_to_write == 0) { - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), - base::Bind(callback, nullptr)), - {}); - return; - } - - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&SSLStream::Write, weak_ptr_factory_.GetWeakPtr(), - buffer, size_to_write, callback), - base::TimeDelta::FromSeconds(1)); - - return; - } - - int err = SSL_get_error(ssl_.get(), res); - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&SSLStream::Write, weak_ptr_factory_.GetWeakPtr(), - buffer, size_to_write, callback), - base::TimeDelta::FromSeconds(1)); - return; - } - - ErrorPtr weave_error; - Error::AddTo(&weave_error, FROM_HERE, "ssl", "socket_write_failed", - "SSL error"); - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&SSLStream::RunDelayedTask, weak_ptr_factory_.GetWeakPtr(), - base::Bind(callback, base::Passed(&weave_error))), - {}); - return; -} - -void SSLStream::CancelPendingOperations() { - weak_ptr_factory_.InvalidateWeakPtrs(); -} - -bool SSLStream::Init(const std::string& host, uint16_t port) { - ctx_.reset(SSL_CTX_new(TLSv1_2_client_method())); - CHECK(ctx_); - ssl_.reset(SSL_new(ctx_.get())); - - char end_point[255]; - snprintf(end_point, sizeof(end_point), "%s:%u", host.c_str(), port); - BIO* stream_bio = BIO_new_connect(end_point); - CHECK(stream_bio); - BIO_set_nbio(stream_bio, 1); - - while (BIO_do_connect(stream_bio) != 1) { - CHECK(BIO_should_retry(stream_bio)); - sleep(1); - } - - SSL_set_bio(ssl_.get(), stream_bio, stream_bio); - SSL_set_connect_state(ssl_.get()); - - for (;;) { - int res = SSL_do_handshake(ssl_.get()); - if (res) { - return true; - } - - res = SSL_get_error(ssl_.get(), res); - - if (res != SSL_ERROR_WANT_READ || res != SSL_ERROR_WANT_WRITE) { - return false; - } - - sleep(1); - } - return false; -} - -} // namespace examples -} // namespace weave
diff --git a/libweave/examples/ubuntu/ssl_stream.h b/libweave/examples/ubuntu/ssl_stream.h deleted file mode 100644 index ae0e539..0000000 --- a/libweave/examples/ubuntu/ssl_stream.h +++ /dev/null
@@ -1,52 +0,0 @@ -// 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. - -#ifndef LIBWEAVE_EXAMPLES_UBUNTU_SSL_STREAM_H_ -#define LIBWEAVE_EXAMPLES_UBUNTU_SSL_STREAM_H_ - -#include <openssl/ssl.h> - -#include <base/memory/weak_ptr.h> -#include <weave/stream.h> - -namespace weave { - -namespace provider { -class TaskRunner; -} - -namespace examples { - -class SSLStream : public Stream { - public: - explicit SSLStream(provider::TaskRunner* task_runner); - - ~SSLStream() override; - - void Read(void* buffer, - size_t size_to_read, - const ReadCallback& callback) override; - - void Write(const void* buffer, - size_t size_to_write, - const WriteCallback& callback) override; - - void CancelPendingOperations() override; - - bool Init(const std::string& host, uint16_t port); - - private: - void RunDelayedTask(const base::Closure& task); - - provider::TaskRunner* task_runner_{nullptr}; - std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx_{nullptr, SSL_CTX_free}; - std::unique_ptr<SSL, decltype(&SSL_free)> ssl_{nullptr, SSL_free}; - - base::WeakPtrFactory<SSLStream> weak_ptr_factory_{this}; -}; - -} // namespace examples -} // namespace weave - -#endif // LIBWEAVE_EXAMPLES_UBUNTU_SSL_STREAM_H_
diff --git a/libweave/examples/ubuntu/weave.gyp b/libweave/examples/ubuntu/weave.gyp deleted file mode 100644 index a561c9d..0000000 --- a/libweave/examples/ubuntu/weave.gyp +++ /dev/null
@@ -1,53 +0,0 @@ -# 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. -{ - 'targets': [ - { - 'target_name': 'weave', - 'type': 'executable', - 'variables': { - 'deps': [ - 'avahi-client', - 'expat', - 'libcurl', - 'libcrypto', - 'openssl', - ] - }, - 'cflags': [ - '>!@(pkg-config >(deps) --cflags)', - '-pthread', - ], - 'link_settings': { - 'ldflags+': [ - '>!@(pkg-config >(deps) --libs-only-L --libs-only-other)', - ], - 'libraries+': [ - '>!(pkg-config >(deps) --libs-only-l)', - ], - }, - 'sources': [ - 'avahi_client.cc', - 'bluez_client.cc', - 'curl_http_client.cc', - 'event_http_client.cc', - 'event_http_server.cc', - 'event_task_runner.cc', - 'file_config_store.cc', - 'main.cc', - 'event_network.cc', - 'network_manager.cc', - 'ssl_stream.cc', - ], - 'dependencies': [ - '../../libweave_standalone.gyp:libweave', - ], - 'libraries': [ - '-levent', - '-levent_openssl', - '-lpthread', - ] - } - ] -}
diff --git a/libweave/libweave_common.gypi b/libweave/libweave_common.gypi index 125047d..bf81f76 100644 --- a/libweave/libweave_common.gypi +++ b/libweave/libweave_common.gypi
@@ -18,6 +18,7 @@ ], 'cflags': [ '-Og', + '-g3', ], }, },
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc index 48361b9..8945b66 100644 --- a/libweave/src/device_registration_info.cc +++ b/libweave/src/device_registration_info.cc
@@ -41,7 +41,16 @@ namespace { const int kPollingPeriodSeconds = 7; -const int kBackupPollingPeriodSeconds = 30; +const int kBackupPollingPeriodMinutes = 30; + +namespace fetch_reason { + +const char kDeviceStart[] = "device_start"; // Initial queue fetch at startup. +const char kRegularPull[] = "regular_pull"; // Regular fetch before XMPP is up. +const char kNewCommand[] = "new_command"; // A new command is available. +const char kJustInCase[] = "just_in_case"; // Backup fetch when XMPP is live. + +} // namespace fetch_reason using provider::HttpClient; @@ -789,7 +798,7 @@ LOG(INFO) << "Device connected to cloud server"; connected_to_cloud_ = true; FetchCommands(base::Bind(&DeviceRegistrationInfo::ProcessInitialCommandList, - AsWeakPtr())); + AsWeakPtr()), fetch_reason::kDeviceStart); // In case there are any pending state updates since we sent off the initial // UpdateDeviceResource() request, update the server with any state changes. PublishStateUpdates(); @@ -985,29 +994,33 @@ fetch_commands_request_sent_ = false; // If we have additional requests queued, send them out now. if (fetch_commands_request_queued_) - FetchAndPublishCommands(); + FetchAndPublishCommands(queued_fetch_reason_); } void DeviceRegistrationInfo::FetchCommands( - const base::Callback<void(const base::ListValue&, ErrorPtr error)>& - callback) { + const base::Callback<void(const base::ListValue&, ErrorPtr)>& callback, + const std::string& reason) { fetch_commands_request_sent_ = true; fetch_commands_request_queued_ = false; DoCloudRequest( HttpClient::Method::kGet, - GetServiceURL("commands/queue", {{"deviceId", GetSettings().cloud_id}}), + GetServiceURL("commands/queue", {{"deviceId", GetSettings().cloud_id}, + {"reason", reason}}), nullptr, base::Bind(&DeviceRegistrationInfo::OnFetchCommandsDone, AsWeakPtr(), callback)); } -void DeviceRegistrationInfo::FetchAndPublishCommands() { +void DeviceRegistrationInfo::FetchAndPublishCommands( + const std::string& reason) { if (fetch_commands_request_sent_) { fetch_commands_request_queued_ = true; + queued_fetch_reason_ = reason; return; } FetchCommands(base::Bind(&DeviceRegistrationInfo::PublishCommands, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr()), + reason); } void DeviceRegistrationInfo::ProcessInitialCommandList( @@ -1183,7 +1196,7 @@ CHECK_EQ(primary_notification_channel_->GetName(), channel_name); notification_channel_starting_ = false; pull_channel_->UpdatePullInterval( - base::TimeDelta::FromSeconds(kBackupPollingPeriodSeconds)); + base::TimeDelta::FromMinutes(kBackupPollingPeriodMinutes)); current_notification_channel_ = primary_notification_channel_.get(); // If we have not successfully connected to the cloud server and we have not @@ -1200,7 +1213,7 @@ UpdateDeviceResource( base::Bind(&IgnoreCloudErrorWithCallback, base::Bind(&DeviceRegistrationInfo::FetchAndPublishCommands, - AsWeakPtr()))); + AsWeakPtr(), fetch_reason::kRegularPull))); } void DeviceRegistrationInfo::OnDisconnected() { @@ -1222,7 +1235,8 @@ } void DeviceRegistrationInfo::OnCommandCreated( - const base::DictionaryValue& command) { + const base::DictionaryValue& command, + const std::string& channel_name) { if (!connected_to_cloud_) return; @@ -1234,10 +1248,21 @@ PublishCommand(command); return; } + + // If this request comes from a Pull channel while the primary notification + // channel (XMPP) is active, we are doing a backup poll, so mark the request + // appropriately. + bool just_in_case = + (channel_name == kPullChannelName) && + (current_notification_channel_ == primary_notification_channel_.get()); + + std::string reason = + just_in_case ? fetch_reason::kJustInCase : fetch_reason::kNewCommand; + // If the command was too big to be delivered over a notification channel, // or OnCommandCreated() was initiated from the Pull notification, // perform a manual command fetch from the server here. - FetchAndPublishCommands(); + FetchAndPublishCommands(reason); } void DeviceRegistrationInfo::OnDeviceDeleted(const std::string& cloud_id) {
diff --git a/libweave/src/device_registration_info.h b/libweave/src/device_registration_info.h index 8eb0ec3..f3bacc6 100644 --- a/libweave/src/device_registration_info.h +++ b/libweave/src/device_registration_info.h
@@ -210,7 +210,8 @@ bool UpdateDeviceInfoTimestamp(const base::DictionaryValue& device_info); void FetchCommands( - const base::Callback<void(const base::ListValue&, ErrorPtr)>& callback); + const base::Callback<void(const base::ListValue&, ErrorPtr)>& callback, + const std::string& reason); void OnFetchCommandsDone( const base::Callback<void(const base::ListValue&, ErrorPtr)>& callback, const base::DictionaryValue& json, @@ -230,7 +231,9 @@ // Helper function to pull the pending command list from the server using // FetchCommands() and make them available on D-Bus with PublishCommands(). - void FetchAndPublishCommands(); + // |backup_fetch| is set to true when performing backup ("just-in-case") + // command fetch while XMPP channel is up and running. + void FetchAndPublishCommands(const std::string& reason); void PublishStateUpdates(); void OnPublishStateDone(StateChangeQueueInterface::UpdateID update_id, @@ -258,7 +261,8 @@ void OnConnected(const std::string& channel_name) override; void OnDisconnected() override; void OnPermanentFailure() override; - void OnCommandCreated(const base::DictionaryValue& command) override; + void OnCommandCreated(const base::DictionaryValue& command, + const std::string& channel_name) override; void OnDeviceDeleted(const std::string& cloud_id) override; // Wipes out the device registration information and stops server connections. @@ -316,6 +320,8 @@ // Set to true when another command queue fetch request is queued while // another one was in flight. bool fetch_commands_request_queued_{false}; + // Specifies the reason for queued command fetch request. + std::string queued_fetch_reason_; using ResourceUpdateCallbackList = std::vector<DoneCallback>; // Callbacks for device resource update request currently in flight to the
diff --git a/libweave/src/device_registration_info_unittest.cc b/libweave/src/device_registration_info_unittest.cc index 060e5c4..a885b7b 100644 --- a/libweave/src/device_registration_info_unittest.cc +++ b/libweave/src/device_registration_info_unittest.cc
@@ -596,14 +596,14 @@ http_client_, SendRequest(HttpClient::Method::kPatch, command_url_, HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _)) - .WillOnce(WithArgs<3, 4>(Invoke([]( - const std::string& data, - const HttpClient::SendRequestCallback& callback) { - EXPECT_JSON_EQ(R"({"state":"done", "results":{"status":"Ok"}})", - *CreateDictionaryValue(data)); - base::DictionaryValue json; - callback.Run(ReplyWithJson(200, json), nullptr); - }))); + .WillOnce(WithArgs<3, 4>( + Invoke([](const std::string& data, + const HttpClient::SendRequestCallback& callback) { + EXPECT_JSON_EQ(R"({"state":"done", "results":{"status":"Ok"}})", + *CreateDictionaryValue(data)); + base::DictionaryValue json; + callback.Run(ReplyWithJson(200, json), nullptr); + }))); EXPECT_TRUE( command_->Complete(*CreateDictionaryValue("{'status': 'Ok'}"), nullptr)); }
diff --git a/libweave/src/notification/notification_delegate.h b/libweave/src/notification/notification_delegate.h index feb9d17..719d76d 100644 --- a/libweave/src/notification/notification_delegate.h +++ b/libweave/src/notification/notification_delegate.h
@@ -18,7 +18,8 @@ virtual void OnDisconnected() = 0; virtual void OnPermanentFailure() = 0; // Called when a new command is sent via the notification channel. - virtual void OnCommandCreated(const base::DictionaryValue& command) = 0; + virtual void OnCommandCreated(const base::DictionaryValue& command, + const std::string& channel_name) = 0; // Called when DEVICE_DELETED notification is received. virtual void OnDeviceDeleted(const std::string& cloud_id) = 0;
diff --git a/libweave/src/notification/notification_parser.cc b/libweave/src/notification/notification_parser.cc index 25c525f..0a27f1c 100644 --- a/libweave/src/notification/notification_parser.cc +++ b/libweave/src/notification/notification_parser.cc
@@ -12,14 +12,15 @@ // Processes COMMAND_CREATED notifications. bool ParseCommandCreated(const base::DictionaryValue& notification, - NotificationDelegate* delegate) { + NotificationDelegate* delegate, + const std::string& channel_name) { const base::DictionaryValue* command = nullptr; if (!notification.GetDictionary("command", &command)) { LOG(ERROR) << "COMMAND_CREATED notification is missing 'command' property"; return false; } - delegate->OnCommandCreated(*command); + delegate->OnCommandCreated(*command, channel_name); return true; } @@ -39,7 +40,8 @@ } // anonymous namespace bool ParseNotificationJson(const base::DictionaryValue& notification, - NotificationDelegate* delegate) { + NotificationDelegate* delegate, + const std::string& channel_name) { CHECK(delegate); std::string kind; @@ -57,7 +59,7 @@ } if (type == "COMMAND_CREATED") - return ParseCommandCreated(notification, delegate); + return ParseCommandCreated(notification, delegate, channel_name); if (type == "DEVICE_DELETED") return ParseDeviceDeleted(notification, delegate);
diff --git a/libweave/src/notification/notification_parser.h b/libweave/src/notification/notification_parser.h index ed62d10..01932c7 100644 --- a/libweave/src/notification/notification_parser.h +++ b/libweave/src/notification/notification_parser.h
@@ -17,7 +17,8 @@ // the appropriate method from the |delegate|. // Returns false if unexpected or malformed notification is received. bool ParseNotificationJson(const base::DictionaryValue& notification, - NotificationDelegate* delegate); + NotificationDelegate* delegate, + const std::string& channel_name); } // namespace weave
diff --git a/libweave/src/notification/notification_parser_unittest.cc b/libweave/src/notification/notification_parser_unittest.cc index 146208f..d0b43fe 100644 --- a/libweave/src/notification/notification_parser_unittest.cc +++ b/libweave/src/notification/notification_parser_unittest.cc
@@ -17,12 +17,17 @@ using test::CreateDictionaryValue; +MATCHER_P(MatchDict, str, "") { + return arg.Equals(CreateDictionaryValue(str).get()); +} + class MockNotificationDelegate : public NotificationDelegate { public: MOCK_METHOD1(OnConnected, void(const std::string&)); MOCK_METHOD0(OnDisconnected, void()); MOCK_METHOD0(OnPermanentFailure, void()); - MOCK_METHOD1(OnCommandCreated, void(const base::DictionaryValue& command)); + MOCK_METHOD2(OnCommandCreated, void(const base::DictionaryValue& command, + const std::string& channel_name)); MOCK_METHOD1(OnDeviceDeleted, void(const std::string&)); }; @@ -51,14 +56,6 @@ "commandId": "command_id" })"); - base::DictionaryValue command_instance; - auto on_command = [&command_instance](const base::DictionaryValue& command) { - command_instance.MergeDictionary(&command); - }; - - EXPECT_CALL(delegate_, OnCommandCreated(_)).WillOnce(Invoke(on_command)); - EXPECT_TRUE(ParseNotificationJson(*json, &delegate_)); - const char expected_json[] = R"({ "kind": "clouddevices#command", "deviceId": "device_id", @@ -71,7 +68,10 @@ "id": "command_id", "creationTimeMs": "1403444174811" })"; - EXPECT_JSON_EQ(expected_json, command_instance); + + EXPECT_CALL(delegate_, OnCommandCreated(MatchDict(expected_json), "foo")) + .Times(1); + EXPECT_TRUE(ParseNotificationJson(*json, &delegate_, "foo")); } TEST_F(NotificationParserTest, DeviceDeleted) { @@ -83,7 +83,7 @@ std::string device_id; EXPECT_CALL(delegate_, OnDeviceDeleted(_)).WillOnce(SaveArg<0>(&device_id)); - EXPECT_TRUE(ParseNotificationJson(*json, &delegate_)); + EXPECT_TRUE(ParseNotificationJson(*json, &delegate_, "foo")); EXPECT_EQ("some_device_id", device_id); } @@ -106,7 +106,7 @@ "commandId": "command_id" })"); - EXPECT_FALSE(ParseNotificationJson(*json, &delegate_)); + EXPECT_FALSE(ParseNotificationJson(*json, &delegate_, "bar")); } TEST_F(NotificationParserTest, Failure_NoType) { @@ -128,7 +128,7 @@ "commandId": "command_id" })"); - EXPECT_FALSE(ParseNotificationJson(*json, &delegate_)); + EXPECT_FALSE(ParseNotificationJson(*json, &delegate_, "baz")); } TEST_F(NotificationParserTest, IgnoredNotificationType) { @@ -151,7 +151,7 @@ "commandId": "command_id" })"); - EXPECT_TRUE(ParseNotificationJson(*json, &delegate_)); + EXPECT_TRUE(ParseNotificationJson(*json, &delegate_, "quux")); } } // namespace weave
diff --git a/libweave/src/notification/pull_channel.cc b/libweave/src/notification/pull_channel.cc index b192df6..378351a 100644 --- a/libweave/src/notification/pull_channel.cc +++ b/libweave/src/notification/pull_channel.cc
@@ -12,12 +12,14 @@ namespace weave { +const char kPullChannelName[] = "pull"; + PullChannel::PullChannel(base::TimeDelta pull_interval, provider::TaskRunner* task_runner) : pull_interval_{pull_interval}, task_runner_{task_runner} {} std::string PullChannel::GetName() const { - return "pull"; + return kPullChannelName; } bool PullChannel::IsConnected() const { @@ -58,7 +60,7 @@ // Repost before delegate notification to give it a chance to stop channel. RePost(); base::DictionaryValue empty_dict; - delegate_->OnCommandCreated(empty_dict); + delegate_->OnCommandCreated(empty_dict, GetName()); } } // namespace weave
diff --git a/libweave/src/notification/pull_channel.h b/libweave/src/notification/pull_channel.h index a48b9f6..7f859e8 100644 --- a/libweave/src/notification/pull_channel.h +++ b/libweave/src/notification/pull_channel.h
@@ -20,6 +20,8 @@ class TaskRunner; } // namespace +extern const char kPullChannelName[]; + class PullChannel : public NotificationChannel { public: PullChannel(base::TimeDelta pull_interval, provider::TaskRunner* task_runner);
diff --git a/libweave/src/notification/xmpp_channel.cc b/libweave/src/notification/xmpp_channel.cc index bca4c3b..ceb45ed 100644 --- a/libweave/src/notification/xmpp_channel.cc +++ b/libweave/src/notification/xmpp_channel.cc
@@ -279,7 +279,7 @@ VLOG(2) << "XMPP push notification data: " << json_data; auto json_dict = LoadJsonDict(json_data, nullptr); if (json_dict && delegate_) - ParseNotificationJson(*json_dict, delegate_); + ParseNotificationJson(*json_dict, delegate_, GetName()); } void XmppChannel::CreateSslSocket() {
diff --git a/libweave/src/privet/security_manager.cc b/libweave/src/privet/security_manager.cc index 8b1500c..1b4e3c5 100644 --- a/libweave/src/privet/security_manager.cc +++ b/libweave/src/privet/security_manager.cc
@@ -24,6 +24,10 @@ #include "src/string_utils.h" #include "third_party/chromium/crypto/p224_spake.h" +#if !defined(ARCH_CPU_LITTLE_ENDIAN) +#error "Big-endian is not supported. See b/25017606" +#endif + namespace weave { namespace privet {