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 {