Merge remote-tracking branch 'origin/master' into merge-to-aosp Merged the following commits: - e61717c Fix the virtual lock device - f1fa93d Add fd event support to EventTaskRunner - 5ca27be Removing trailing whitespace from speaker.cc - b51b475 Adding handler for speaker device. - fdf7515 examples: fix prerequisites for debian - 82f215e Fixed check for pending tasks - a627e12 Run CURL in background thread.
diff --git a/examples/daemon/README b/examples/daemon/README index 287459f..c767420 100644 --- a/examples/daemon/README +++ b/examples/daemon/README
@@ -8,8 +8,8 @@ examples/prerequisites.sh - build daemon examples/build.sh - - binaries for daemon is at - out/Debug/weave_daemon + - binaries for daemon are in the directory + out/Debug/ Prepare Host OS --------------- @@ -50,7 +50,7 @@ 93019287-6b26-04a0-22ee-d55ad23a4226 - go to terminal, register and start the daemon with - sudo out/Debug/weave_daemon --registration_ticket=93019287-6b26-04a0-22ee-d55ad23a4226 + sudo out/Debug/weave_daemon_sample --registration_ticket=93019287-6b26-04a0-22ee-d55ad23a4226 you should see something like: Publishing service
diff --git a/examples/daemon/examples.gyp b/examples/daemon/examples.gyp index 8fee90d..2b497a5 100644 --- a/examples/daemon/examples.gyp +++ b/examples/daemon/examples.gyp
@@ -7,7 +7,8 @@ 'sample/daemon.gyp:weave_daemon_sample', 'light/daemon.gyp:weave_daemon_light', 'lock/daemon.gyp:weave_daemon_lock', - 'ledflasher/daemon.gyp:weave_daemon_ledflasher' + 'ledflasher/daemon.gyp:weave_daemon_ledflasher', + 'speaker/daemon.gyp:weave_daemon_speaker' ] } ]
diff --git a/examples/daemon/lock/lock.cc b/examples/daemon/lock/lock.cc index e1ca2d9..3014fb1 100644 --- a/examples/daemon/lock/lock.cc +++ b/examples/daemon/lock/lock.cc
@@ -34,11 +34,16 @@ device_ = device; device->AddStateDefinitionsFromJson(R"({ - "lock": {"lockedState": ["locked", "unlocked", "partiallyLocked"]} + "lock": { + "lockedState": ["locked", "unlocked", "partiallyLocked"], + "isLockingSupported": "boolean"} })"); device->SetStatePropertiesFromJson(R"({ - "lock":{"lockedState": "locked"} + "lock":{ + "lockedState": "locked", + "isLockingSupported": true + } })", nullptr);
diff --git a/examples/daemon/speaker/daemon.gyp b/examples/daemon/speaker/daemon.gyp new file mode 100644 index 0000000..3bf7a91 --- /dev/null +++ b/examples/daemon/speaker/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_speaker', + 'type': 'executable', + 'sources': [ + 'speaker.cc', + ], + 'dependencies': [ + '<@(DEPTH)/libweave_standalone.gyp:libweave', + '<@(DEPTH)/examples/provider/provider.gyp:libweave_provider', + ] + } + ] +}
diff --git a/examples/daemon/speaker/speaker.cc b/examples/daemon/speaker/speaker.cc new file mode 100644 index 0000000..32591f9 --- /dev/null +++ b/examples/daemon/speaker/speaker.cc
@@ -0,0 +1,154 @@ +// 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/daemon/common/daemon.h" + +#include <weave/device.h> + +#include <base/bind.h> +#include <base/memory/weak_ptr.h> + +// SpeakerHandler is a command handler example that shows +// how to handle commands for a Weave speaker. +class SpeakerHandler { + public: + SpeakerHandler() = default; + void Register(weave::Device* device) { + device_ = device; + + device->AddStateDefinitionsFromJson(R"({ + "onOff": {"state": ["on", "standby"]}, + "volume": { + "volume": "integer", + "isMuted": "boolean" + } + })"); + + device->SetStatePropertiesFromJson(R"({ + "onOff":{"state": "standby"}, + "volume":{ + "volume": 100, + "isMuted": false + } + })", + nullptr); + + device->AddCommandDefinitionsFromJson(R"({ + "onOff": { + "setConfig":{ + "parameters": { + "state": ["on", "standby"] + } + } + }, + "volume": { + "setConfig":{ + "parameters": { + "volume": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "isMuted": "boolean" + } + } + } + })"); + device->AddCommandHandler("onOff.setConfig", + base::Bind(&SpeakerHandler::OnOnOffSetConfig, + weak_ptr_factory_.GetWeakPtr())); + device->AddCommandHandler("volume.setConfig", + base::Bind(&SpeakerHandler::OnVolumeSetConfig, + weak_ptr_factory_.GetWeakPtr())); + } + + private: + void OnVolumeSetConfig(const std::weak_ptr<weave::Command>& command) { + auto cmd = command.lock(); + if (!cmd) + return; + LOG(INFO) << "received command: " << cmd->GetName(); + + // Handle volume parameter + int32_t volume_value = 0; + if (cmd->GetParameters()->GetInteger("volume", &volume_value)) { + // Display this command in terminal. + LOG(INFO) << cmd->GetName() << " volume: " << volume_value; + + if (volume_value_ != volume_value) { + volume_value_ = volume_value; + UpdateSpeakerState(); + } + cmd->Complete({}, nullptr); + return; + } + + // Handle isMuted parameter + bool isMuted_status = false; + if (cmd->GetParameters()->GetBoolean("isMuted", &isMuted_status)) { + // Display this command in terminal. + LOG(INFO) << cmd->GetName() << " is " + << (isMuted_status ? "muted" : "not muted"); + + if (isMuted_status_ != isMuted_status) { + isMuted_status_ = isMuted_status; + + LOG(INFO) << "Speaker is now: " + << (isMuted_status ? "muted" : "not muted"); + UpdateSpeakerState(); + } + } + + cmd->Complete({}, nullptr); + } + + void OnOnOffSetConfig(const std::weak_ptr<weave::Command>& command) { + auto cmd = command.lock(); + if (!cmd) + return; + LOG(INFO) << "received command: " << cmd->GetName(); + std::string requested_state; + if (cmd->GetParameters()->GetString("state", &requested_state)) { + LOG(INFO) << cmd->GetName() << " state: " << requested_state; + + bool new_speaker_status = requested_state == "on"; + if (new_speaker_status != speaker_status_) { + speaker_status_ = new_speaker_status; + + LOG(INFO) << "Speaker is now: " << (speaker_status_ ? "ON" : "OFF"); + UpdateSpeakerState(); + } + } + cmd->Complete({}, nullptr); + } + + void UpdateSpeakerState() { + base::DictionaryValue state; + state.SetString("onOff.state", speaker_status_ ? "on" : "standby"); + state.SetBoolean("volume.isMuted", isMuted_status_); + state.SetInteger("volume.volume", volume_value_); + device_->SetStateProperties(state, nullptr); + } + + weave::Device* device_{nullptr}; + + // Simulate the state of the speaker. + bool speaker_status_; + bool isMuted_status_; + int32_t volume_value_; + base::WeakPtrFactory<SpeakerHandler> weak_ptr_factory_{this}; +}; + +int main(int argc, char** argv) { + Daemon::Options opts; + if (!opts.Parse(argc, argv)) { + Daemon::Options::ShowUsage(argv[0]); + return 1; + } + Daemon daemon{opts}; + SpeakerHandler speaker; + speaker.Register(daemon.GetDevice()); + daemon.Run(); + return 0; +}
diff --git a/examples/prerequisites.sh b/examples/prerequisites.sh index d1661d0..7358b71 100755 --- a/examples/prerequisites.sh +++ b/examples/prerequisites.sh
@@ -6,10 +6,11 @@ DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) ROOT_DIR=$(cd -P -- "$(dirname -- "$0")/.." && pwd -P) -sudo apt-get install ${APT_GET_OPTS} \ +sudo apt-get update && sudo apt-get install ${APT_GET_OPTS} \ autoconf \ automake \ binutils \ + g++ \ gyp \ hostapd \ libavahi-client-dev \ @@ -17,6 +18,7 @@ libexpat1-dev \ libnl-3-dev \ libnl-route-3-dev \ + libssl-dev \ libtool \ ninja-build \ || exit 1 @@ -57,8 +59,10 @@ ./autogen.sh || exit 1 ./configure --disable-shared || exit 1 make || exit 1 -echo -e "\n\nTesting libevent...\nCan take several minutes.\n" -make verify || exit 1 +if [ -z "$DISABLE_LIBEVENT_TEST" ]; then + echo -e "\n\nTesting libevent...\nCan take several minutes.\n" + make verify || exit 1 +fi cp -rf include/* $ROOT_DIR/third_party/include/ || exit 1 cp -rf .libs/lib* $ROOT_DIR/third_party/lib/ || exit 1 rm -rf $ROOT_DIR/third_party/libevent
diff --git a/examples/provider/curl_http_client.cc b/examples/provider/curl_http_client.cc index b440f39..32aa4af 100644 --- a/examples/provider/curl_http_client.cc +++ b/examples/provider/curl_http_client.cc
@@ -4,10 +4,14 @@ #include "examples/provider/curl_http_client.h" +#include <future> +#include <thread> + #include <base/bind.h> +#include <base/logging.h> #include <curl/curl.h> -#include <weave/provider/task_runner.h> #include <weave/enum_to_string.h> +#include <weave/provider/task_runner.h> namespace weave { namespace examples { @@ -30,29 +34,24 @@ return size * nmemb; } -} // namespace - -CurlHttpClient::CurlHttpClient(provider::TaskRunner* task_runner) - : task_runner_{task_runner} {} - -void CurlHttpClient::SendRequest(Method method, - const std::string& url, - const Headers& headers, - const std::string& data, - const SendRequestCallback& callback) { +std::pair<std::unique_ptr<CurlHttpClient::Response>, ErrorPtr> +SendRequestBlocking(CurlHttpClient::Method method, + const std::string& url, + const CurlHttpClient::Headers& headers, + const std::string& data) { std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> curl{curl_easy_init(), &curl_easy_cleanup}; CHECK(curl); switch (method) { - case Method::kGet: + case CurlHttpClient::Method::kGet: CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HTTPGET, 1L)); break; - case Method::kPost: + case CurlHttpClient::Method::kPost: CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HTTPPOST, 1L)); break; - case Method::kPatch: - case Method::kPut: + case CurlHttpClient::Method::kPatch: + case CurlHttpClient::Method::kPut: CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_CUSTOMREQUEST, weave::EnumToString(method).c_str())); break; @@ -66,7 +65,7 @@ CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, chunk)); - if (!data.empty() || method == Method::kPost) { + if (!data.empty() || method == CurlHttpClient::Method::kPost) { CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, data.c_str())); } @@ -89,8 +88,7 @@ if (res != CURLE_OK) { Error::AddTo(&error, FROM_HERE, "curl", "curl_easy_perform_error", curl_easy_strerror(res)); - return task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)), {}); + return {nullptr, std::move(error)}; } const std::string kContentType = "\r\nContent-Type:"; @@ -98,8 +96,7 @@ if (pos == std::string::npos) { Error::AddTo(&error, FROM_HERE, "curl", "no_content_header", "Content-Type header is missing"); - return task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)), {}); + return {nullptr, std::move(error)}; } pos += kContentType.size(); auto pos_end = response->content_type.find("\r\n", pos); @@ -112,8 +109,57 @@ CHECK_EQ(CURLE_OK, curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &response->status)); + return {std::move(response), nullptr}; +} + +} // namespace + +CurlHttpClient::CurlHttpClient(provider::TaskRunner* task_runner) + : task_runner_{task_runner} {} + +void CurlHttpClient::SendRequest(Method method, + const std::string& url, + const Headers& headers, + const std::string& data, + const SendRequestCallback& callback) { + pending_tasks_.emplace_back( + std::async(std::launch::async, SendRequestBlocking, method, url, headers, + data), + callback); + if (pending_tasks_.size() == 1) // More means check is scheduled. + CheckTasks(); +} + +void CurlHttpClient::CheckTasks() { + VLOG(4) << "CurlHttpClient::CheckTasks, size=" << pending_tasks_.size(); + auto ready_begin = + std::partition(pending_tasks_.begin(), pending_tasks_.end(), + [](const decltype(pending_tasks_)::value_type& value) { + return value.first.wait_for(std::chrono::seconds(0)) != + std::future_status::ready; + }); + + for (auto it = ready_begin; it != pending_tasks_.end(); ++it) { + CHECK(it->first.valid()); + auto result = it->first.get(); + VLOG(2) << "CurlHttpClient::CheckTasks done"; + task_runner_->PostDelayedTask( + FROM_HERE, base::Bind(it->second, base::Passed(&result.first), + base::Passed(&result.second)), + {}); + } + + pending_tasks_.erase(ready_begin, pending_tasks_.end()); + + if (pending_tasks_.empty()) { + VLOG(2) << "No more CurlHttpClient tasks"; + return; + } + task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(callback, base::Passed(&response), nullptr), {}); + FROM_HERE, + base::Bind(&CurlHttpClient::CheckTasks, weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(100)); } } // namespace examples
diff --git a/examples/provider/curl_http_client.h b/examples/provider/curl_http_client.h index b2f4bca..c342076 100644 --- a/examples/provider/curl_http_client.h +++ b/examples/provider/curl_http_client.h
@@ -5,7 +5,9 @@ #ifndef LIBWEAVE_EXAMPLES_PROVIDER_CURL_HTTP_CLIENT_H_ #define LIBWEAVE_EXAMPLES_PROVIDER_CURL_HTTP_CLIENT_H_ +#include <future> #include <string> +#include <utility> #include <base/memory/weak_ptr.h> #include <weave/provider/http_client.h> @@ -31,6 +33,11 @@ const SendRequestCallback& callback) override; private: + void CheckTasks(); + + std::vector< + std::pair<std::future<std::pair<std::unique_ptr<Response>, ErrorPtr>>, + SendRequestCallback>> pending_tasks_; provider::TaskRunner* task_runner_{nullptr}; base::WeakPtrFactory<CurlHttpClient> weak_ptr_factory_{this};
diff --git a/examples/provider/event_deleter.h b/examples/provider/event_deleter.h new file mode 100644 index 0000000..078c326 --- /dev/null +++ b/examples/provider/event_deleter.h
@@ -0,0 +1,37 @@ +// 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_EVENT_DELETER_H +#define LIBWEAVE_EXAMPLES_PROVIDER_EVENT_DELETER_H + +#include <memory> + +#include <third_party/include/event2/event.h> +#include <third_party/include/event2/event_struct.h> +#include <third_party/include/event2/http.h> + +namespace weave { +namespace examples { + +// Defines overloaded deletion methods for various event_ objects +// so we can use one unique_ptr definition for all of them +class EventDeleter { + public: + void operator()(evhttp_uri* http_uri) { evhttp_uri_free(http_uri); } + void operator()(evhttp_connection* conn) { evhttp_connection_free(conn); } + void operator()(evhttp_request* req) { evhttp_request_free(req); } + void operator()(event_base* base) { event_base_free(base); } + void operator()(event* ev) { + event_del(ev); + event_free(ev); + } +}; + +template <typename T> +using EventPtr = std::unique_ptr<T, EventDeleter>; + +} // namespace examples +} // namespace weave + +#endif // LIBWEAVE_EXAMPLES_PROVIDER_EVENT_DELETER_H
diff --git a/examples/provider/event_http_client.cc b/examples/provider/event_http_client.cc index b38bd55..03da97f 100644 --- a/examples/provider/event_http_client.cc +++ b/examples/provider/event_http_client.cc
@@ -5,15 +5,14 @@ #include "examples/provider/event_http_client.h" #include "examples/provider/event_task_runner.h" -#include <weave/enum_to_string.h> - -#include <string> #include <base/bind.h> - #include <event2/bufferevent.h> #include <event2/buffer.h> #include <event2/http.h> +#include <weave/enum_to_string.h> + +#include "examples/provider/event_deleter.h" // EventHttpClient based on libevent2 http-client sample // TODO(proppy): https @@ -38,13 +37,6 @@ namespace { -class EventDeleter { - public: - void operator()(evhttp_uri* http_uri) { evhttp_uri_free(http_uri); } - void operator()(evhttp_connection* conn) { evhttp_connection_free(conn); } - void operator()(evhttp_request* req) { evhttp_request_free(req); } -}; - class EventHttpResponse : public weave::provider::HttpClient::Response { public: int GetStatusCode() const override { return status; } @@ -58,8 +50,8 @@ struct EventRequestState { TaskRunner* task_runner_; - std::unique_ptr<evhttp_uri, EventDeleter> http_uri_; - std::unique_ptr<evhttp_connection, EventDeleter> evcon_; + EventPtr<evhttp_uri> http_uri_; + EventPtr<evhttp_connection> evcon_; HttpClient::SendRequestCallback callback_; }; @@ -101,8 +93,7 @@ const SendRequestCallback& callback) { evhttp_cmd_type method_id; CHECK(weave::StringToEnum(weave::EnumToString(method), &method_id)); - std::unique_ptr<evhttp_uri, EventDeleter> http_uri{ - evhttp_uri_parse(url.c_str())}; + EventPtr<evhttp_uri> http_uri{evhttp_uri_parse(url.c_str())}; CHECK(http_uri); auto host = evhttp_uri_get_host(http_uri.get()); CHECK(host); @@ -121,11 +112,10 @@ auto bev = bufferevent_socket_new(task_runner_->GetEventBase(), -1, BEV_OPT_CLOSE_ON_FREE); CHECK(bev); - std::unique_ptr<evhttp_connection, EventDeleter> conn{ - evhttp_connection_base_bufferevent_new(task_runner_->GetEventBase(), NULL, - bev, host, port)}; + EventPtr<evhttp_connection> conn{evhttp_connection_base_bufferevent_new( + task_runner_->GetEventBase(), NULL, bev, host, port)}; CHECK(conn); - std::unique_ptr<evhttp_request, EventDeleter> req{evhttp_request_new( + EventPtr<evhttp_request> req{evhttp_request_new( &RequestDoneCallback, new EventRequestState{task_runner_, std::move(http_uri), std::move(conn), callback})};
diff --git a/examples/provider/event_http_client.h b/examples/provider/event_http_client.h index 7ad117e..378c4a3 100644 --- a/examples/provider/event_http_client.h +++ b/examples/provider/event_http_client.h
@@ -10,11 +10,11 @@ #include <base/memory/weak_ptr.h> #include <weave/provider/http_client.h> +#include "examples/provider/event_task_runner.h" + namespace weave { namespace examples { -class EventTaskRunner; - // Basic implementation of weave::HttpClient using libevent. class EventHttpClient : public provider::HttpClient { public:
diff --git a/examples/provider/event_task_runner.cc b/examples/provider/event_task_runner.cc index c14a934..c07e912 100644 --- a/examples/provider/event_task_runner.cc +++ b/examples/provider/event_task_runner.cc
@@ -24,6 +24,24 @@ queue_.emplace(std::make_pair(new_time, ++counter_), task); } +void EventTaskRunner::AddIoCompletionTask( + int fd, + int16_t what, + const EventTaskRunner::IoCompletionCallback& task) { + int16_t flags = EV_PERSIST | EV_ET; + flags |= (what & kReadable) ? EV_READ : 0; + flags |= (what & kWriteable) ? EV_WRITE : 0; + flags |= (what & kClosed) ? EV_CLOSED : 0; + event* ioevent = event_new(base_.get(), fd, flags, FdEventHandler, this); + EventPtr<event> ioeventPtr{ioevent}; + fd_task_map_.emplace(fd, std::make_pair(std::move(ioeventPtr), task)); + event_add(ioevent, nullptr); +} + +void EventTaskRunner::RemoveIoCompletionTask(int fd) { + fd_task_map_.erase(fd); +} + void EventTaskRunner::Run() { g_event_base = base_.get(); @@ -44,7 +62,9 @@ event_add(task_event_.get(), &tv); } -void EventTaskRunner::EventHandler(int, int16_t, void* runner) { +void EventTaskRunner::EventHandler(int /* fd */, + int16_t /* what */, + void* runner) { static_cast<EventTaskRunner*>(runner)->Process(); } @@ -66,5 +86,17 @@ } } +void EventTaskRunner::FdEventHandler(int fd, int16_t what, void* runner) { + static_cast<EventTaskRunner*>(runner)->ProcessFd(fd, what); +} + +void EventTaskRunner::ProcessFd(int fd, int16_t what) { + auto it = fd_task_map_.find(fd); + if (it != fd_task_map_.end()) { + const IoCompletionCallback& callback = it->second.second; + callback.Run(fd, what, this); + } +} + } // namespace examples } // namespace weave
diff --git a/examples/provider/event_task_runner.h b/examples/provider/event_task_runner.h index 473441e..7291314 100644 --- a/examples/provider/event_task_runner.h +++ b/examples/provider/event_task_runner.h
@@ -10,9 +10,10 @@ #include <vector> #include <event2/event.h> - #include <weave/provider/task_runner.h> +#include "examples/provider/event_deleter.h" + namespace weave { namespace examples { @@ -23,6 +24,40 @@ const base::Closure& task, base::TimeDelta delay) override; + // Defines the types of I/O completion events that the + // application can register to receive on a file descriptor. + enum IOEvent : int16_t { + kReadable = 0x01, + kWriteable = 0x02, + kClosed = 0x04, + kReadableWriteable = kReadable | kWriteable, + kReadableOrClosed = kReadable | kClosed, + kAll = kReadableOrClosed | kWriteable, + }; + + // Callback type for I/O completion events. + // Arguments: + // fd - file descriptor that triggered the event + // what - combination of IOEvent flags indicating + // which event(s) occurred + // sender - reference to the EventTaskRunner that + // called the IoCompletionCallback + using IoCompletionCallback = + base::Callback<void(int fd, int16_t what, EventTaskRunner* sender)>; + + // Adds a handler for the specified IO completion events on a file + // descriptor. The 'what' parameter is a combination of IOEvent flags. + // Only one callback is allowed per file descriptor; calling this function + // with an fd that has already been registered will replace the previous + // callback with the new one. + void AddIoCompletionTask(int fd, + int16_t what, + const IoCompletionCallback& task); + + // Remove the callback associated with this fd and stop listening for + // events related to it. + void RemoveIoCompletionTask(int fd); + event_base* GetEventBase() const { return base_.get(); } void Run(); @@ -33,6 +68,9 @@ static void FreeEvent(event* evnt); void Process(); + static void FdEventHandler(int fd, int16_t what, void* runner); + void ProcessFd(int fd, int16_t what); + using QueueItem = std::pair<std::pair<base::Time, size_t>, base::Closure>; struct Greater { @@ -47,10 +85,12 @@ std::vector<QueueItem>, EventTaskRunner::Greater> queue_; - std::unique_ptr<event_base, decltype(&event_base_free)> base_{ - event_base_new(), &event_base_free}; - std::unique_ptr<event, decltype(&FreeEvent)> task_event_{ - event_new(base_.get(), -1, EV_TIMEOUT, &EventHandler, this), &FreeEvent}; + EventPtr<event_base> base_{event_base_new()}; + + EventPtr<event> task_event_{ + event_new(base_.get(), -1, EV_TIMEOUT, &EventHandler, this)}; + + std::map<int, std::pair<EventPtr<event>, IoCompletionCallback>> fd_task_map_; }; } // namespace examples
diff --git a/examples/provider/wifi_manager.cc b/examples/provider/wifi_manager.cc index 6e216e4..ed6a9fd 100644 --- a/examples/provider/wifi_manager.cc +++ b/examples/provider/wifi_manager.cc
@@ -42,7 +42,7 @@ WifiImpl::WifiImpl(provider::TaskRunner* task_runner, EventNetworkImpl* network) : task_runner_{task_runner}, network_{network} { - CHECK_EQ(0, getuid()) + CHECK_EQ(0u, getuid()) << "WiFi manager expects root access to control WiFi capabilities"; StopAccessPoint(); }