aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Vakulenko <avakulenko@google.com>2016-02-02 12:31:43 -0800
committerAlex Vakulenko <avakulenko@google.com>2016-02-02 12:33:52 -0800
commite851e48e0f6e71af1ed25c982aae51cac0004f28 (patch)
tree6f6ec4e0215e5fb7dab58640dcc49c27ef4923cc
parent9d187e6ddb3c0a570dd363c77cab2dc7f4966260 (diff)
parent98d1fee994302f5e2ad7a7b60de2f2d74f35408b (diff)
downloadlibweave-e851e48e0f6e71af1ed25c982aae51cac0004f28.tar.gz
Merge remote-tracking branch 'weave/master' into 'weave/aosp-master'
919a8a9 Remove crypto type "None" 3313558 Replace bleeding-edge libevent with libevhtp. c3d7714 Make default Makefile target "all". d9e3061 Add libevent-dev to README. ebfa60b Add a unit tests for deleting CloudCommandProxy along with CommandInstance c920bb2 Fix memory leak when removing CommandInstance from CommandQueue 329ad80 Rename CommandQueue::DelayedRemove into RemoveLater() 6a1ba84 Changed meaning of some SSID flags 98d1fee Periodicly clean up command queue and remove old processed commands Change-Id: If63cb3d9a34d405df06ab958c609bb46668737bc
-rw-r--r--.gitignore2
-rw-r--r--Makefile4
-rw-r--r--README.md29
-rw-r--r--examples/daemon/common/daemon.h7
-rw-r--r--examples/examples.mk16
-rw-r--r--examples/provider/event_deleter.h23
-rw-r--r--examples/provider/event_http_server.cc146
-rw-r--r--examples/provider/event_http_server.h30
-rw-r--r--examples/provider/event_task_runner.cc6
-rw-r--r--examples/provider/file_config_store.cc7
-rw-r--r--examples/provider/file_config_store.h4
-rw-r--r--examples/provider/wifi_manager.h2
-rw-r--r--include/weave/provider/test/fake_task_runner.h1
-rw-r--r--include/weave/provider/test/mock_wifi.h2
-rw-r--r--include/weave/provider/wifi.h3
-rw-r--r--include/weave/settings.h1
-rw-r--r--src/base_api_handler_unittest.cc4
-rw-r--r--src/commands/cloud_command_proxy.h2
-rw-r--r--src/commands/cloud_command_proxy_unittest.cc41
-rw-r--r--src/commands/command_instance.cc2
-rw-r--r--src/commands/command_instance.h5
-rw-r--r--src/commands/command_queue.cc40
-rw-r--r--src/commands/command_queue.h35
-rw-r--r--src/commands/command_queue_unittest.cc60
-rw-r--r--src/component_manager_impl.cc6
-rw-r--r--src/component_manager_impl.h3
-rw-r--r--src/component_manager_unittest.cc4
-rw-r--r--src/config_unittest.cc3
-rw-r--r--src/device_manager.cc2
-rw-r--r--src/device_registration_info_unittest.cc2
-rw-r--r--src/privet/privet_manager.cc5
-rw-r--r--src/privet/privet_manager.h1
-rw-r--r--src/privet/privet_types.cc1
-rw-r--r--src/privet/privet_types.h1
-rw-r--r--src/privet/security_manager.cc31
-rw-r--r--src/privet/wifi_bootstrap_manager.cc16
-rw-r--r--src/privet/wifi_ssid_generator.cc17
-rw-r--r--src/privet/wifi_ssid_generator.h2
-rw-r--r--src/privet/wifi_ssid_generator_unittest.cc28
-rw-r--r--src/test/fake_task_runner.cc4
-rw-r--r--src/weave_unittest.cc5
-rwxr-xr-xthird_party/get_libevent.sh29
-rwxr-xr-xthird_party/get_libevhtp.sh25
-rw-r--r--third_party/third_party.mk24
44 files changed, 396 insertions, 285 deletions
diff --git a/.gitignore b/.gitignore
index a256906..86c649b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,6 @@
/out/
/third_party/include
/third_party/lib
+/third_party/libevhtp
+/third_party/googletest
gomacc.lock
diff --git a/Makefile b/Makefile
index de69f40..df27b58 100644
--- a/Makefile
+++ b/Makefile
@@ -88,7 +88,6 @@ include file_lists.mk third_party/third_party.mk examples/examples.mk tests.mk
weave_obj_files := $(WEAVE_SRC_FILES:%.cc=out/$(BUILD_MODE)/%.o)
-# TODO(jacobmarble): There are too many gtest/gmock deps in non-test targets. Fix.
$(weave_obj_files) : out/$(BUILD_MODE)/%.o : %.cc
mkdir -p $(dir $@)
$(CXX) $(DEFS_$(BUILD_MODE)) $(INCLUDES) $(CFLAGS) $(CFLAGS_$(BUILD_MODE)) $(CFLAGS_CC) -c -o $@ $<
@@ -102,7 +101,8 @@ all : out/$(BUILD_MODE)/libweave.so all-examples out/$(BUILD_MODE)/libweave_expo
clean :
rm -rf out
-cleanall : clean clean-gtest clean-libevent
+cleanall : clean clean-gtest clean-libevhtp
.PHONY : clean cleanall all
+.DEFAULT_GOAL := all
diff --git a/README.md b/README.md
index fc042b7..211033c 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,20 @@ repo sync
```
sudo apt-get update
-sudo apt-get install autoconf automake binutils g++ hostapd libavahi-client-dev libcurl4-openssl-dev libexpat1-dev libnl-3-dev libnl-route-3-dev libssl-dev libtool
+sudo apt-get install \
+ autoconf \
+ automake \
+ binutils \
+ g++ \
+ hostapd \
+ libavahi-client-dev \
+ libcurl4-openssl-dev \
+ libevent-dev \
+ libexpat1-dev \
+ libnl-3-dev \
+ libnl-route-3-dev \
+ libssl-dev \
+ libtool
```
# Prerequisites
@@ -72,7 +85,8 @@ sudo apt-get install autoconf automake binutils g++ hostapd libavahi-client-dev
- hostapd
- libavahi-client-dev
- libcurl4-openssl-dev
- - libevent 2.1.x-alpha (included; see third_party/get_libevent.sh)
+ - libevent 2.0.x
+ - libevhtp (included; see third_party/get_libevhtp.sh)
# Compiling
@@ -80,17 +94,16 @@ sudo apt-get install autoconf automake binutils g++ hostapd libavahi-client-dev
The `make --jobs/-j` flag is encouraged, to speed up build time. For example
```
-make all -j
+make -j
```
-### Build library
-
-```
-make
+which happens to be the same as
```
+make all -j
+````
-or
+### Build library
```
make out/Debug/libweave.so
diff --git a/examples/daemon/common/daemon.h b/examples/daemon/common/daemon.h
index 6dc021d..985c5e5 100644
--- a/examples/daemon/common/daemon.h
+++ b/examples/daemon/common/daemon.h
@@ -20,7 +20,6 @@ class Daemon {
public:
struct Options {
bool force_bootstrapping_{false};
- bool disable_security_{false};
bool disable_privet_{false};
std::string registration_ticket_;
std::string model_id_{"AAAAA"};
@@ -31,7 +30,6 @@ class Daemon {
<< "\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";
@@ -44,8 +42,6 @@ class Daemon {
return false;
} 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) {
@@ -71,8 +67,7 @@ class Daemon {
Daemon(const Options& opts)
: task_runner_{new weave::examples::EventTaskRunner},
config_store_{
- new weave::examples::FileConfigStore(opts.disable_security_,
- opts.model_id_,
+ new weave::examples::FileConfigStore(opts.model_id_,
task_runner_.get())},
http_client_{new weave::examples::CurlHttpClient(task_runner_.get())},
network_{new weave::examples::EventNetworkImpl(task_runner_.get())},
diff --git a/examples/examples.mk b/examples/examples.mk
index 06266a3..f1e92b6 100644
--- a/examples/examples.mk
+++ b/examples/examples.mk
@@ -7,7 +7,7 @@
examples_provider_obj_files := $(EXAMPLES_PROVIDER_SRC_FILES:%.cc=out/$(BUILD_MODE)/%.o)
-$(examples_provider_obj_files) : out/$(BUILD_MODE)/%.o : %.cc third_party/include/event2/event.h
+$(examples_provider_obj_files) : out/$(BUILD_MODE)/%.o : %.cc third_party/include/evhtp.h
mkdir -p $(dir $@)
$(CXX) $(DEFS_$(BUILD_MODE)) $(INCLUDES) $(CFLAGS) $(CFLAGS_$(BUILD_MODE)) $(CFLAGS_CC) -c -o $@ $<
@@ -15,7 +15,7 @@ out/$(BUILD_MODE)/examples_provider.a : $(examples_provider_obj_files)
rm -f $@
$(AR) crsT $@ $^
-out/$(BUILD_MODE)/examples/daemon/%.o : examples/daemon/%.cc third_party/include/event2/event.h
+out/$(BUILD_MODE)/examples/daemon/%.o : examples/daemon/%.cc third_party/include/evhtp.h
mkdir -p $(dir $@)
$(CXX) $(DEFS_$(BUILD_MODE)) $(INCLUDES) $(CFLAGS) $(CFLAGS_$(BUILD_MODE)) $(CFLAGS_CC) -c -o $@ $<
@@ -32,22 +32,22 @@ daemon_common_flags := \
-lssl \
-lcrypto
-out/$(BUILD_MODE)/weave_daemon_ledflasher : out/$(BUILD_MODE)/examples/daemon/ledflasher/ledflasher.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so
+out/$(BUILD_MODE)/weave_daemon_ledflasher : out/$(BUILD_MODE)/examples/daemon/ledflasher/ledflasher.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so third_party/lib/libevhtp.a
$(CXX) -o $@ $^ $(CFLAGS) $(daemon_common_flags)
-out/$(BUILD_MODE)/weave_daemon_light : out/$(BUILD_MODE)/examples/daemon/light/light.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so
+out/$(BUILD_MODE)/weave_daemon_light : out/$(BUILD_MODE)/examples/daemon/light/light.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so third_party/lib/libevhtp.a
$(CXX) -o $@ $^ $(CFLAGS) $(daemon_common_flags)
-out/$(BUILD_MODE)/weave_daemon_lock : out/$(BUILD_MODE)/examples/daemon/lock/lock.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so
+out/$(BUILD_MODE)/weave_daemon_lock : out/$(BUILD_MODE)/examples/daemon/lock/lock.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so third_party/lib/libevhtp.a
$(CXX) -o $@ $^ $(CFLAGS) $(daemon_common_flags)
-out/$(BUILD_MODE)/weave_daemon_oven : out/$(BUILD_MODE)/examples/daemon/oven/oven.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so
+out/$(BUILD_MODE)/weave_daemon_oven : out/$(BUILD_MODE)/examples/daemon/oven/oven.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so third_party/lib/libevhtp.a
$(CXX) -o $@ $^ $(CFLAGS) $(daemon_common_flags)
-out/$(BUILD_MODE)/weave_daemon_sample : out/$(BUILD_MODE)/examples/daemon/sample/sample.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so
+out/$(BUILD_MODE)/weave_daemon_sample : out/$(BUILD_MODE)/examples/daemon/sample/sample.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so third_party/lib/libevhtp.a
$(CXX) -o $@ $^ $(CFLAGS) $(daemon_common_flags)
-out/$(BUILD_MODE)/weave_daemon_speaker : out/$(BUILD_MODE)/examples/daemon/speaker/speaker.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so
+out/$(BUILD_MODE)/weave_daemon_speaker : out/$(BUILD_MODE)/examples/daemon/speaker/speaker.o out/$(BUILD_MODE)/examples_provider.a out/$(BUILD_MODE)/libweave.so third_party/lib/libevhtp.a
$(CXX) -o $@ $^ $(CFLAGS) $(daemon_common_flags)
all-examples : out/$(BUILD_MODE)/weave_daemon_ledflasher out/$(BUILD_MODE)/weave_daemon_light out/$(BUILD_MODE)/weave_daemon_lock out/$(BUILD_MODE)/weave_daemon_oven out/$(BUILD_MODE)/weave_daemon_sample out/$(BUILD_MODE)/weave_daemon_speaker
diff --git a/examples/provider/event_deleter.h b/examples/provider/event_deleter.h
index 078c326..9bb53f4 100644
--- a/examples/provider/event_deleter.h
+++ b/examples/provider/event_deleter.h
@@ -7,9 +7,10 @@
#include <memory>
-#include <third_party/include/event2/event.h>
-#include <third_party/include/event2/event_struct.h>
-#include <third_party/include/event2/http.h>
+#include <evhtp.h>
+#include <event2/event.h>
+#include <event2/event_struct.h>
+#include <openssl/ssl.h>
namespace weave {
namespace examples {
@@ -18,9 +19,19 @@ namespace examples {
// 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()(evbuffer* buf) { evbuffer_free(buf); }
+ void operator()(evhtp_t* evhtp) {
+ if (evhtp->ssl_ctx) {
+ // Work around a double-free bug in recent versions of libevhtp.
+ // https://github.com/ellzey/libevhtp/pull/208
+ SSL_CTX_free(evhtp->ssl_ctx);
+ evhtp->ssl_ctx = nullptr;
+ }
+ evhtp_unbind_socket(evhtp);
+ evhtp_free(evhtp);
+ }
+ void operator()(evhtp_connection_t* conn) { evhtp_connection_free(conn); }
+ void operator()(evhtp_request_t* req) { evhtp_request_free(req); }
void operator()(event_base* base) { event_base_free(base); }
void operator()(event* ev) {
event_del(ev);
diff --git a/examples/provider/event_http_server.cc b/examples/provider/event_http_server.cc
index ae9833e..1bf58f6 100644
--- a/examples/provider/event_http_server.cc
+++ b/examples/provider/event_http_server.cc
@@ -9,6 +9,7 @@
#include <base/bind.h>
#include <base/time/time.h>
#include <event2/bufferevent_ssl.h>
+#include <evhtp.h>
#include <openssl/err.h>
#include "examples/provider/event_task_runner.h"
@@ -24,53 +25,45 @@ std::string GetSslError() {
return error;
}
-bufferevent* BuffetEventCallback(event_base* base, void* arg) {
- SSL_CTX* ctx = static_cast<SSL_CTX*>(arg);
- return bufferevent_openssl_socket_new(
- base, -1, SSL_new(ctx), BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_CLOSE_ON_FREE);
-}
-
} // namespace
class HttpServerImpl::RequestImpl : public Request {
public:
- RequestImpl(evhttp_request* req) {
- req_.reset(req);
- uri_ = evhttp_request_get_evhttp_uri(req_.get());
-
- data_.resize(evbuffer_get_length(req_->input_buffer));
- evbuffer_remove(req_->input_buffer, &data_[0], data_.size());
+ RequestImpl(EventPtr<evhtp_request_t> req) : req_(std::move(req)) {
+ evbuf_t* input_buffer =
+ bufferevent_get_input(evhtp_request_get_bev(req_.get()));
+ data_.resize(evbuffer_get_length(input_buffer));
+ evbuffer_remove(input_buffer, &data_[0], data_.size());
}
~RequestImpl() {}
- std::string GetPath() const override {
- const char* path = evhttp_uri_get_path(uri_);
- return path ? path : "";
- }
+ std::string GetPath() const override { return req_->uri->path->path; }
+
std::string GetFirstHeader(const std::string& name) const override {
- const char* header = evhttp_find_header(req_->input_headers, name.c_str());
+ const char* header = evhtp_header_find(req_->headers_in, name.c_str());
if (!header)
return {};
return header;
}
+
std::string GetData() { return data_; }
void SendReply(int status_code,
const std::string& data,
const std::string& mime_type) override {
- std::unique_ptr<evbuffer, decltype(&evbuffer_free)> buf{evbuffer_new(),
- &evbuffer_free};
+ EventPtr<evbuffer> buf{evbuffer_new()};
evbuffer_add(buf.get(), data.data(), data.size());
- evhttp_add_header(req_->output_headers, "Content-Type", mime_type.c_str());
- evhttp_send_reply(req_.release(), status_code, "None", buf.get());
+ evhtp_header_key_add(req_->headers_out, "Content-Type", 0);
+ evhtp_header_val_add(req_->headers_out, mime_type.c_str(), 1);
+ evhtp_send_reply_start(req_.get(), status_code);
+ evhtp_send_reply_body(req_.get(), buf.get());
+ evhtp_send_reply_end(req_.get());
}
private:
- std::unique_ptr<evhttp_request, decltype(&evhttp_cancel_request)> req_{
- nullptr, &evhttp_cancel_request};
+ EventPtr<evhtp_request_t> req_;
std::string data_;
- const evhttp_uri* uri_{nullptr};
};
HttpServerImpl::HttpServerImpl(EventTaskRunner* task_runner)
@@ -78,74 +71,75 @@ HttpServerImpl::HttpServerImpl(EventTaskRunner* task_runner)
SSL_load_error_strings();
SSL_library_init();
- ctx_.reset(SSL_CTX_new(TLSv1_2_server_method()));
- SSL_CTX_set_options(ctx_.get(), SSL_OP_SINGLE_DH_USE |
- SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_SSLv2);
-
- ec_key_.reset(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
- CHECK(ec_key_) << GetSslError();
- CHECK_EQ(1, SSL_CTX_set_tmp_ecdh(ctx_.get(), ec_key_.get())) << GetSslError();
-
- GenerateX509();
- CHECK_EQ(1, SSL_CTX_use_PrivateKey(ctx_.get(), pkey_.get())) << GetSslError();
- CHECK_EQ(1, SSL_CTX_use_certificate(ctx_.get(), x509_.get()))
- << GetSslError();
-
- CHECK_EQ(1, SSL_CTX_check_private_key(ctx_.get())) << GetSslError();
-
- httpd_.reset(evhttp_new(task_runner_->GetEventBase()));
+ std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx{
+ SSL_CTX_new(TLSv1_2_server_method()), &SSL_CTX_free};
+ CHECK(ctx);
+ SSL_CTX_set_options(ctx.get(), SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE |
+ SSL_OP_NO_SSLv2);
+
+ std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> ec_key{
+ EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), &EC_KEY_free};
+ CHECK(ec_key) << GetSslError();
+ CHECK_EQ(1, SSL_CTX_set_tmp_ecdh(ctx.get(), ec_key.get())) << GetSslError();
+
+ std::unique_ptr<X509, decltype(&X509_free)> x509{X509_new(), &X509_free};
+ CHECK(x509);
+ std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> pkey{EVP_PKEY_new(),
+ &EVP_PKEY_free};
+ CHECK(pkey);
+ GenerateX509(x509.get(), pkey.get());
+ CHECK_EQ(1, SSL_CTX_use_PrivateKey(ctx.get(), pkey.get())) << GetSslError();
+ CHECK_EQ(1, SSL_CTX_use_certificate(ctx.get(), x509.get())) << GetSslError();
+
+ CHECK_EQ(1, SSL_CTX_check_private_key(ctx.get())) << GetSslError();
+
+ httpd_.reset(evhtp_new(task_runner_->GetEventBase(), nullptr));
CHECK(httpd_);
- httpsd_.reset(evhttp_new(task_runner_->GetEventBase()));
+ httpsd_.reset(evhtp_new(task_runner_->GetEventBase(), nullptr));
CHECK(httpsd_);
- evhttp_set_bevcb(httpsd_.get(), BuffetEventCallback, ctx_.get());
+ httpsd_.get()->ssl_ctx = ctx.release();
- CHECK_EQ(0, evhttp_bind_socket(httpd_.get(), "0.0.0.0", GetHttpPort()));
- CHECK_EQ(0, evhttp_bind_socket(httpsd_.get(), "0.0.0.0", GetHttpsPort()));
+ CHECK_EQ(0, evhtp_bind_socket(httpd_.get(), "0.0.0.0", GetHttpPort(), -1));
+ CHECK_EQ(0, evhtp_bind_socket(httpsd_.get(), "0.0.0.0", GetHttpsPort(), -1));
}
-void HttpServerImpl::GenerateX509() {
- x509_.reset(X509_new());
- CHECK(x509_) << GetSslError();
+void HttpServerImpl::GenerateX509(X509* x509, EVP_PKEY* pkey) {
+ CHECK(x509) << GetSslError();
- X509_set_version(x509_.get(), 2);
+ X509_set_version(x509, 2);
- X509_gmtime_adj(X509_get_notBefore(x509_.get()), 0);
- X509_gmtime_adj(X509_get_notAfter(x509_.get()),
+ X509_gmtime_adj(X509_get_notBefore(x509), 0);
+ X509_gmtime_adj(X509_get_notAfter(x509),
base::TimeDelta::FromDays(365).InSeconds());
- pkey_.reset(EVP_PKEY_new());
- CHECK(pkey_) << GetSslError();
+ CHECK(pkey) << GetSslError();
std::unique_ptr<BIGNUM, decltype(&BN_free)> big_num(BN_new(), &BN_free);
CHECK(BN_set_word(big_num.get(), 65537)) << GetSslError();
auto rsa = RSA_new();
RSA_generate_key_ex(rsa, 2048, big_num.get(), nullptr);
- CHECK(EVP_PKEY_assign_RSA(pkey_.get(), rsa)) << GetSslError();
+ CHECK(EVP_PKEY_assign_RSA(pkey, rsa)) << GetSslError();
- X509_set_pubkey(x509_.get(), pkey_.get());
+ X509_set_pubkey(x509, pkey);
- CHECK(X509_sign(x509_.get(), pkey_.get(), EVP_sha256())) << GetSslError();
+ CHECK(X509_sign(x509, pkey, EVP_sha256())) << GetSslError();
cert_fingerprint_.resize(EVP_MD_size(EVP_sha256()));
uint32_t len = 0;
- CHECK(X509_digest(x509_.get(), EVP_sha256(), cert_fingerprint_.data(), &len));
+ CHECK(X509_digest(x509, EVP_sha256(), cert_fingerprint_.data(), &len));
CHECK_EQ(len, cert_fingerprint_.size());
}
-void HttpServerImpl::ProcessRequestCallback(evhttp_request* req, void* arg) {
- static_cast<HttpServerImpl*>(arg)->ProcessRequest(req);
-}
-
-void HttpServerImpl::NotFound(evhttp_request* req) {
- std::unique_ptr<evbuffer, decltype(&evbuffer_free)> buf{evbuffer_new(),
- &evbuffer_free};
- evbuffer_add_printf(buf.get(), "404 Not Found: %s\n",
- evhttp_request_uri(req));
- evhttp_send_reply(req, 404, "Not Found", buf.get());
+void HttpServerImpl::NotFound(evhtp_request_t* req) {
+ EventPtr<evbuffer> buf{evbuffer_new()};
+ evbuffer_add_printf(buf.get(), "404 Not Found: %s\n", req->uri->path->path);
+ evhtp_send_reply_start(req, 404);
+ evhtp_send_reply_body(req, buf.get());
+ evhtp_send_reply_end(req);
}
-void HttpServerImpl::ProcessRequest(evhttp_request* req) {
- std::unique_ptr<RequestImpl> request{new RequestImpl{req}};
+void HttpServerImpl::ProcessRequest(evhtp_request_t* req) {
+ std::unique_ptr<RequestImpl> request{new RequestImpl{EventPtr<evhtp_request_t>{req}}};
std::string path = request->GetPath();
auto it = handlers_.find(path);
if (it != handlers_.end()) {
@@ -154,25 +148,29 @@ void HttpServerImpl::ProcessRequest(evhttp_request* req) {
NotFound(req);
}
-void HttpServerImpl::ProcessReply(std::shared_ptr<RequestImpl> request,
- int status_code,
- const std::string& data,
- const std::string& mime_type) {}
+void HttpServerImpl::ProcessRequestCallback(evhtp_request_t* req, void* arg) {
+ static_cast<HttpServerImpl*>(arg)->ProcessRequest(req);
+}
void HttpServerImpl::AddHttpRequestHandler(
const std::string& path,
const RequestHandlerCallback& callback) {
handlers_.insert(std::make_pair(path, callback));
- evhttp_set_cb(httpd_.get(), path.c_str(), &ProcessRequestCallback, this);
+ evhtp_set_cb(httpd_.get(), path.c_str(), &ProcessRequestCallback, this);
}
void HttpServerImpl::AddHttpsRequestHandler(
const std::string& path,
const RequestHandlerCallback& callback) {
handlers_.insert(std::make_pair(path, callback));
- evhttp_set_cb(httpsd_.get(), path.c_str(), &ProcessRequestCallback, this);
+ evhtp_set_cb(httpsd_.get(), path.c_str(), &ProcessRequestCallback, this);
}
+void HttpServerImpl::ProcessReply(std::shared_ptr<RequestImpl> request,
+ int status_code,
+ const std::string& data,
+ const std::string& mime_type) {}
+
uint16_t HttpServerImpl::GetHttpPort() const {
return 7780;
}
diff --git a/examples/provider/event_http_server.h b/examples/provider/event_http_server.h
index 950e536..8bb5dd9 100644
--- a/examples/provider/event_http_server.h
+++ b/examples/provider/event_http_server.h
@@ -5,8 +5,7 @@
#ifndef LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_SERVER_H_
#define LIBWEAVE_EXAMPLES_PROVIDER_EVENT_HTTP_SERVER_H_
-#include <event2/http.h>
-#include <evhttp.h>
+#include <evhtp.h>
#include <openssl/ssl.h>
#include <map>
@@ -16,12 +15,14 @@
#include <base/memory/weak_ptr.h>
#include <weave/provider/http_server.h>
+#include "examples/provider/event_deleter.h"
+
namespace weave {
namespace examples {
class EventTaskRunner;
-// HTTP/HTTPS server implemented with libevent.
+// HTTP/HTTPS server implemented with libevhtp.
class HttpServerImpl : public provider::HttpServer {
public:
class RequestImpl;
@@ -38,32 +39,21 @@ class HttpServerImpl : public provider::HttpServer {
std::vector<uint8_t> GetHttpsCertificateFingerprint() const override;
private:
- void GenerateX509();
- static void ProcessRequestCallback(evhttp_request* req, void* arg);
- void ProcessRequest(evhttp_request* req);
+ void GenerateX509(X509* x509, EVP_PKEY* pkey);
+ static void ProcessRequestCallback(evhtp_request_t* req, void* arg);
+ void ProcessRequest(evhtp_request_t* req);
void ProcessReply(std::shared_ptr<RequestImpl> request,
int status_code,
const std::string& data,
const std::string& mime_type);
- void NotFound(evhttp_request* req);
+ void NotFound(evhtp_request_t* req);
std::map<std::string, RequestHandlerCallback> handlers_;
- std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> ec_key_{nullptr,
- &EC_KEY_free};
-
- std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> pkey_{nullptr,
- &EVP_PKEY_free};
-
- std::unique_ptr<X509, decltype(&X509_free)> x509_{nullptr, &X509_free};
-
- std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx_{nullptr,
- &SSL_CTX_free};
std::vector<uint8_t> cert_fingerprint_;
EventTaskRunner* task_runner_{nullptr};
- std::unique_ptr<evhttp, decltype(&evhttp_free)> httpd_{nullptr, &evhttp_free};
- std::unique_ptr<evhttp, decltype(&evhttp_free)> httpsd_{nullptr,
- &evhttp_free};
+ EventPtr<evhtp_t> httpd_;
+ EventPtr<evhtp_t> httpsd_;
base::WeakPtrFactory<HttpServerImpl> weak_ptr_factory_{this};
};
diff --git a/examples/provider/event_task_runner.cc b/examples/provider/event_task_runner.cc
index 1d94612..a86ffff 100644
--- a/examples/provider/event_task_runner.cc
+++ b/examples/provider/event_task_runner.cc
@@ -31,7 +31,9 @@ void EventTaskRunner::AddIoCompletionTask(
int16_t flags = EV_PERSIST | EV_ET;
flags |= (what & kReadable) ? EV_READ : 0;
flags |= (what & kWriteable) ? EV_WRITE : 0;
+#if LIBEVENT_VERSION_NUMBER >= 0x02010400
flags |= (what & kClosed) ? EV_CLOSED : 0;
+#endif
event* ioevent = event_new(base_.get(), fd, flags, FdEventHandler, this);
EventPtr<event> ioeventPtr{ioevent};
fd_task_map_.insert(
@@ -53,7 +55,9 @@ void EventTaskRunner::Run() {
sigfillset(&sa.sa_mask);
sigaction(SIGINT, &sa, nullptr);
- event_base_loop(g_event_base, EVLOOP_NO_EXIT_ON_EMPTY);
+ do {
+ event_base_loop(g_event_base, EVLOOP_ONCE);
+ } while (!event_base_got_exit(g_event_base));
g_event_base = nullptr;
}
diff --git a/examples/provider/file_config_store.cc b/examples/provider/file_config_store.cc
index 31efaa7..a6c2e60 100644
--- a/examples/provider/file_config_store.cc
+++ b/examples/provider/file_config_store.cc
@@ -19,11 +19,9 @@ namespace examples {
const char kSettingsDir[] = "/var/lib/weave/";
-FileConfigStore::FileConfigStore(bool disable_security,
- const std::string& model_id,
+FileConfigStore::FileConfigStore(const std::string& model_id,
provider::TaskRunner* task_runner)
- : disable_security_{disable_security},
- model_id_{model_id},
+ : model_id_{model_id},
task_runner_{task_runner} {}
std::string FileConfigStore::GetPath(const std::string& name) const {
@@ -61,7 +59,6 @@ bool FileConfigStore::LoadDefaults(Settings* settings) {
settings->client_secret = "LS_iPYo_WIOE0m2VnLdduhnx";
settings->api_key = "AIzaSyACK3oZtmIylUKXiTMqkZqfuRiCgQmQSAQ";
- settings->disable_security = disable_security_;
return true;
}
diff --git a/examples/provider/file_config_store.h b/examples/provider/file_config_store.h
index e7398d1..337e82a 100644
--- a/examples/provider/file_config_store.h
+++ b/examples/provider/file_config_store.h
@@ -17,8 +17,7 @@ namespace examples {
class FileConfigStore : public provider::ConfigStore {
public:
- FileConfigStore(bool disable_security,
- const std::string& model_id,
+ FileConfigStore(const std::string& model_id,
provider::TaskRunner* task_runner);
bool LoadDefaults(Settings* settings) override;
@@ -31,7 +30,6 @@ class FileConfigStore : public provider::ConfigStore {
private:
std::string GetPath(const std::string& name) const;
- const bool disable_security_;
const std::string model_id_;
provider::TaskRunner* task_runner_{nullptr};
};
diff --git a/examples/provider/wifi_manager.h b/examples/provider/wifi_manager.h
index 2bfc5ca..72f54df 100644
--- a/examples/provider/wifi_manager.h
+++ b/examples/provider/wifi_manager.h
@@ -35,6 +35,8 @@ class WifiImpl : public provider::Wifi {
const DoneCallback& callback) override;
void StartAccessPoint(const std::string& ssid) override;
void StopAccessPoint() override;
+ bool IsWifi24Supported() const override {return true;};
+ bool IsWifi50Supported() const override {return false;};
static bool HasWifiCapability();
diff --git a/include/weave/provider/test/fake_task_runner.h b/include/weave/provider/test/fake_task_runner.h
index bb79455..4080072 100644
--- a/include/weave/provider/test/fake_task_runner.h
+++ b/include/weave/provider/test/fake_task_runner.h
@@ -31,6 +31,7 @@ class FakeTaskRunner : public TaskRunner {
void Run(size_t number_of_iterations = 1000);
void Break();
base::Clock* GetClock();
+ size_t GetTaskQueueSize() const;
private:
void SaveTask(const tracked_objects::Location& from_here,
diff --git a/include/weave/provider/test/mock_wifi.h b/include/weave/provider/test/mock_wifi.h
index 9fbe10f..7ede55e 100644
--- a/include/weave/provider/test/mock_wifi.h
+++ b/include/weave/provider/test/mock_wifi.h
@@ -23,6 +23,8 @@ class MockWifi : public Wifi {
const DoneCallback&));
MOCK_METHOD1(StartAccessPoint, void(const std::string&));
MOCK_METHOD0(StopAccessPoint, void());
+ MOCK_CONST_METHOD0(IsWifi24Supported, bool());
+ MOCK_CONST_METHOD0(IsWifi50Supported, bool());
};
} // namespace test
diff --git a/include/weave/provider/wifi.h b/include/weave/provider/wifi.h
index 48ac651..9c7cfca 100644
--- a/include/weave/provider/wifi.h
+++ b/include/weave/provider/wifi.h
@@ -28,6 +28,9 @@ class Wifi {
// Stops WiFi access point.
virtual void StopAccessPoint() = 0;
+ virtual bool IsWifi24Supported() const = 0;
+ virtual bool IsWifi50Supported() const = 0;
+
protected:
virtual ~Wifi() {}
};
diff --git a/include/weave/settings.h b/include/weave/settings.h
index eeb3f93..741fff2 100644
--- a/include/weave/settings.h
+++ b/include/weave/settings.h
@@ -71,7 +71,6 @@ struct Settings {
// Internal options to tweak some library functionality. External code should
// avoid using them.
bool wifi_auto_setup_enabled{true};
- bool disable_security{false};
std::string test_privet_ssid;
};
diff --git a/src/base_api_handler_unittest.cc b/src/base_api_handler_unittest.cc
index 8b0f0b2..2a202d1 100644
--- a/src/base_api_handler_unittest.cc
+++ b/src/base_api_handler_unittest.cc
@@ -8,6 +8,7 @@
#include <base/time/default_clock.h>
#include <base/values.h>
#include <gtest/gtest.h>
+#include <weave/provider/test/fake_task_runner.h>
#include <weave/provider/test/mock_config_store.h>
#include <weave/provider/test/mock_http_client.h>
#include <weave/test/mock_device.h>
@@ -93,7 +94,8 @@ class BaseApiHandlerTest : public ::testing::Test {
Config config_{&config_store_};
StrictMock<provider::test::MockHttpClient> http_client_;
std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
- ComponentManagerImpl component_manager_;
+ StrictMock<provider::test::FakeTaskRunner> task_runner_;
+ ComponentManagerImpl component_manager_{&task_runner_};
std::unique_ptr<BaseApiHandler> handler_;
StrictMock<test::MockDevice> device_;
};
diff --git a/src/commands/cloud_command_proxy.h b/src/commands/cloud_command_proxy.h
index 13f4654..80efd70 100644
--- a/src/commands/cloud_command_proxy.h
+++ b/src/commands/cloud_command_proxy.h
@@ -29,7 +29,7 @@ class TaskRunner;
}
// Command proxy which publishes command updates to the cloud.
-class CloudCommandProxy final : public CommandInstance::Observer {
+class CloudCommandProxy : public CommandInstance::Observer {
public:
CloudCommandProxy(CommandInstance* command_instance,
CloudCommandUpdateInterface* cloud_command_updater,
diff --git a/src/commands/cloud_command_proxy_unittest.cc b/src/commands/cloud_command_proxy_unittest.cc
index 013769d..0de67fe 100644
--- a/src/commands/cloud_command_proxy_unittest.cc
+++ b/src/commands/cloud_command_proxy_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <queue>
+#include <base/bind.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <weave/provider/test/fake_task_runner.h>
@@ -16,6 +17,7 @@
#include "src/mock_component_manager.h"
using testing::_;
+using testing::AnyNumber;
using testing::DoAll;
using testing::Invoke;
using testing::Return;
@@ -62,6 +64,27 @@ class TestBackoffEntry : public BackoffEntry {
base::Time creation_time_;
};
+class CloudCommandProxyWrapper : public CloudCommandProxy {
+ public:
+ CloudCommandProxyWrapper(CommandInstance* command_instance,
+ CloudCommandUpdateInterface* cloud_command_updater,
+ ComponentManager* component_manager,
+ std::unique_ptr<BackoffEntry> backoff_entry,
+ provider::TaskRunner* task_runner,
+ const base::Closure& destruct_callback)
+ : CloudCommandProxy{command_instance, cloud_command_updater,
+ component_manager, std::move(backoff_entry),
+ task_runner},
+ destruct_callback_{destruct_callback} {}
+
+ ~CloudCommandProxyWrapper() {
+ destruct_callback_.Run();
+ }
+
+ private:
+ base::Closure destruct_callback_;
+};
+
class CloudCommandProxyTest : public ::testing::Test {
protected:
void SetUp() override {
@@ -100,15 +123,21 @@ class CloudCommandProxyTest : public ::testing::Test {
new TestBackoffEntry{&policy, task_runner_.GetClock()}};
// Finally construct the CloudCommandProxy we are going to test here.
- std::unique_ptr<CloudCommandProxy> proxy{new CloudCommandProxy{
+ std::unique_ptr<CloudCommandProxy> proxy{new CloudCommandProxyWrapper{
command_instance_.get(), &cloud_updater_, &component_manager_,
- std::move(backoff), &task_runner_}};
+ std::move(backoff), &task_runner_,
+ base::Bind(&CloudCommandProxyTest::OnProxyDestroyed,
+ base::Unretained(this))}};
// CloudCommandProxy::CloudCommandProxy() subscribe itself to weave::Command
// notifications. When weave::Command is being destroyed it sends
// ::OnCommandDestroyed() and CloudCommandProxy deletes itself.
proxy.release();
+
+ EXPECT_CALL(*this, OnProxyDestroyed()).Times(AnyNumber());
}
+ MOCK_METHOD0(OnProxyDestroyed, void());
+
ComponentManager::UpdateID current_state_update_id_{0};
base::CallbackList<void(ComponentManager::UpdateID)> callbacks_;
testing::StrictMock<MockCloudCommandUpdateInterface> cloud_updater_;
@@ -120,6 +149,14 @@ class CloudCommandProxyTest : public ::testing::Test {
} // anonymous namespace
+TEST_F(CloudCommandProxyTest, EnsureDestroyed) {
+ EXPECT_CALL(*this, OnProxyDestroyed()).Times(1);
+ command_instance_.reset();
+ // Verify that CloudCommandProxy has been destroyed already and not at some
+ // point during the destruction of CloudCommandProxyTest class.
+ testing::Mock::VerifyAndClearExpectations(this);
+}
+
TEST_F(CloudCommandProxyTest, ImmediateUpdate) {
const char expected[] = "{'state':'done'}";
EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _));
diff --git a/src/commands/command_instance.cc b/src/commands/command_instance.cc
index fc9b0e7..590bbb1 100644
--- a/src/commands/command_instance.cc
+++ b/src/commands/command_instance.cc
@@ -284,7 +284,7 @@ bool CommandInstance::SetStatus(Command::State status, ErrorPtr* error) {
void CommandInstance::RemoveFromQueue() {
if (queue_)
- queue_->DelayedRemove(GetID());
+ queue_->RemoveLater(GetID());
}
} // namespace weave
diff --git a/src/commands/command_instance.h b/src/commands/command_instance.h
index b1028d0..febe5c5 100644
--- a/src/commands/command_instance.h
+++ b/src/commands/command_instance.h
@@ -89,10 +89,7 @@ class CommandInstance final : public Command {
// Sets the pointer to queue this command is part of.
void AttachToQueue(CommandQueue* queue) { queue_ = queue; }
- void DetachFromQueue() {
- observers_.Clear();
- queue_ = nullptr;
- }
+ void DetachFromQueue() { queue_ = nullptr; }
private:
// Helper function to update the command status.
diff --git a/src/commands/command_queue.cc b/src/commands/command_queue.cc
index 134dc1c..f0d2228 100644
--- a/src/commands/command_queue.cc
+++ b/src/commands/command_queue.cc
@@ -18,6 +18,10 @@ std::string GetCommandHandlerKey(const std::string& component_path,
}
}
+CommandQueue::CommandQueue(provider::TaskRunner* task_runner,
+ base::Clock* clock)
+ : task_runner_{task_runner}, clock_{clock} {}
+
void CommandQueue::AddCommandAddedCallback(const CommandCallback& callback) {
on_command_added_.push_back(callback);
// Send all pre-existed commands.
@@ -84,18 +88,19 @@ void CommandQueue::Add(std::unique_ptr<CommandInstance> instance) {
it_handler->second.Run(pair.first->second);
else if (!default_command_callback_.is_null())
default_command_callback_.Run(pair.first->second);
-
- Cleanup();
}
-void CommandQueue::DelayedRemove(const std::string& id) {
+void CommandQueue::RemoveLater(const std::string& id) {
auto p = map_.find(id);
if (p == map_.end())
return;
- remove_queue_.push(std::make_pair(
- base::Time::Now() + base::TimeDelta::FromMinutes(kRemoveCommandDelayMin),
- id));
- Cleanup();
+ auto remove_delay = base::TimeDelta::FromMinutes(kRemoveCommandDelayMin);
+ remove_queue_.push(std::make_pair(clock_->Now() + remove_delay, id));
+ if (remove_queue_.size() == 1) {
+ // The queue was empty, this is the first command to be removed, schedule
+ // a clean-up task.
+ ScheduleCleanup(remove_delay);
+ }
}
bool CommandQueue::Remove(const std::string& id) {
@@ -110,19 +115,26 @@ bool CommandQueue::Remove(const std::string& id) {
return true;
}
-void CommandQueue::Cleanup() {
- while (!remove_queue_.empty() && remove_queue_.front().first < Now()) {
- Remove(remove_queue_.front().second);
+void CommandQueue::Cleanup(const base::Time& cutoff_time) {
+ while (!remove_queue_.empty() && remove_queue_.top().first <= cutoff_time) {
+ Remove(remove_queue_.top().second);
remove_queue_.pop();
}
}
-void CommandQueue::SetNowForTest(base::Time now) {
- test_now_ = now;
+void CommandQueue::ScheduleCleanup(base::TimeDelta delay) {
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CommandQueue::PerformScheduledCleanup,
+ weak_ptr_factory_.GetWeakPtr()),
+ delay);
}
-base::Time CommandQueue::Now() const {
- return test_now_.is_null() ? base::Time::Now() : test_now_;
+void CommandQueue::PerformScheduledCleanup() {
+ base::Time now = clock_->Now();
+ Cleanup(now);
+ if (!remove_queue_.empty())
+ ScheduleCleanup(remove_queue_.top().first - now);
}
CommandInstance* CommandQueue::Find(const std::string& id) const {
diff --git a/src/commands/command_queue.h b/src/commands/command_queue.h
index 0f0a18b..a092c12 100644
--- a/src/commands/command_queue.h
+++ b/src/commands/command_queue.h
@@ -14,8 +14,10 @@
#include <base/callback.h>
#include <base/macros.h>
+#include <base/time/default_clock.h>
#include <base/time/time.h>
#include <weave/device.h>
+#include <weave/provider/task_runner.h>
#include "src/commands/command_instance.h"
@@ -23,7 +25,7 @@ namespace weave {
class CommandQueue final {
public:
- CommandQueue() = default;
+ CommandQueue(provider::TaskRunner* task_runner, base::Clock* clock);
// TODO: Remove AddCommandAddedCallback and AddCommandRemovedCallback.
using CommandCallback = base::Callback<void(Command* command)>;
@@ -51,7 +53,7 @@ class CommandQueue final {
// Selects command identified by |id| ready for removal. Command will actually
// be removed after some time.
- void DelayedRemove(const std::string& id);
+ void RemoveLater(const std::string& id);
// Finds a command instance in the queue by the instance |id|. Returns
// nullptr if the command with the given |id| is not found. The returned
@@ -64,23 +66,29 @@ class CommandQueue final {
// Removes a command identified by |id| from the queue.
bool Remove(const std::string& id);
- // Removes old commands selected with DelayedRemove.
- void Cleanup();
+ // Removes old commands scheduled by RemoveLater() to be deleted after
+ // |cutoff_time|.
+ void Cleanup(const base::Time& cutoff_time);
- // Overrides CommandQueue::Now() for tests.
- void SetNowForTest(base::Time now);
+ // Schedule a cleanup task to be run after the specified |delay|.
+ void ScheduleCleanup(base::TimeDelta delay);
- // Returns current time.
- base::Time Now() const;
+ // Perform removal of scheduled commands (by calling Cleanup()) and scheduling
+ // another cleanup task if the removal queue is still not empty.
+ void PerformScheduledCleanup();
- // Overridden value to be returned from Now().
- base::Time test_now_;
+ provider::TaskRunner* task_runner_{nullptr};
+ base::Clock* clock_{nullptr};
// ID-to-CommandInstance map.
std::map<std::string, std::shared_ptr<CommandInstance>> map_;
- // Queue of commands to be removed.
- std::queue<std::pair<base::Time, std::string>> remove_queue_;
+ // Queue of commands to be removed, keeps them sorted by the timestamp
+ // (earliest first). This is done to tolerate system clock changes.
+ template <typename T>
+ using InversePriorityQueue =
+ std::priority_queue<T, std::vector<T>, std::greater<T>>;
+ InversePriorityQueue<std::pair<base::Time, std::string>> remove_queue_;
using CallbackList = std::vector<CommandCallback>;
CallbackList on_command_added_;
@@ -88,6 +96,9 @@ class CommandQueue final {
std::map<std::string, Device::CommandHandlerCallback> command_callbacks_;
Device::CommandHandlerCallback default_command_callback_;
+ // WeakPtr factory for controlling the lifetime of command queue cleanup
+ // tasks.
+ base::WeakPtrFactory<CommandQueue> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CommandQueue);
};
diff --git a/src/commands/command_queue_unittest.cc b/src/commands/command_queue_unittest.cc
index b4c5938..1e2e0ac 100644
--- a/src/commands/command_queue_unittest.cc
+++ b/src/commands/command_queue_unittest.cc
@@ -10,12 +10,18 @@
#include <base/bind.h>
#include <base/memory/weak_ptr.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <weave/provider/test/fake_task_runner.h>
+#include "src/bind_lambda.h"
#include "src/string_utils.h"
namespace weave {
+using testing::Return;
+using testing::StrictMock;
+
class CommandQueueTest : public testing::Test {
public:
std::unique_ptr<CommandInstance> CreateDummyCommandInstance(
@@ -30,11 +36,15 @@ class CommandQueueTest : public testing::Test {
bool Remove(const std::string& id) { return queue_.Remove(id); }
void Cleanup(const base::TimeDelta& interval) {
- queue_.SetNowForTest(base::Time::Now() + interval);
- return queue_.Cleanup();
+ return queue_.Cleanup(task_runner_.GetClock()->Now() + interval);
+ }
+
+ std::string GetFirstCommandToBeRemoved() const {
+ return queue_.remove_queue_.top().second;
}
- CommandQueue queue_;
+ StrictMock<provider::test::FakeTaskRunner> task_runner_;
+ CommandQueue queue_{&task_runner_, task_runner_.GetClock()};
};
// Keeps track of commands being added to and removed from the queue_.
@@ -105,12 +115,12 @@ TEST_F(CommandQueueTest, Remove) {
EXPECT_TRUE(queue_.IsEmpty());
}
-TEST_F(CommandQueueTest, DelayedRemove) {
+TEST_F(CommandQueueTest, RemoveLater) {
const std::string id1 = "id1";
queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
EXPECT_EQ(1u, queue_.GetCount());
- queue_.DelayedRemove(id1);
+ queue_.RemoveLater(id1);
EXPECT_EQ(1u, queue_.GetCount());
Cleanup(base::TimeDelta::FromMinutes(1));
@@ -120,6 +130,46 @@ TEST_F(CommandQueueTest, DelayedRemove) {
EXPECT_EQ(0u, queue_.GetCount());
}
+TEST_F(CommandQueueTest, RemoveLaterOnCleanupTask) {
+ const std::string id1 = "id1";
+ queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
+ EXPECT_EQ(1u, queue_.GetCount());
+
+ queue_.RemoveLater(id1);
+ EXPECT_EQ(1u, queue_.GetCount());
+ ASSERT_EQ(1u, task_runner_.GetTaskQueueSize());
+
+ task_runner_.RunOnce();
+
+ EXPECT_EQ(0u, queue_.GetCount());
+ EXPECT_EQ(0u, task_runner_.GetTaskQueueSize());
+}
+
+TEST_F(CommandQueueTest, CleanupMultipleCommands) {
+ const std::string id1 = "id1";
+ const std::string id2 = "id2";
+
+ queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
+ queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
+ auto remove_task = [this](const std::string& id) { queue_.RemoveLater(id); };
+ remove_task(id1);
+ task_runner_.PostDelayedTask(FROM_HERE, base::Bind(remove_task, id2),
+ base::TimeDelta::FromSeconds(10));
+ EXPECT_EQ(2u, queue_.GetCount());
+ ASSERT_EQ(2u, task_runner_.GetTaskQueueSize());
+ task_runner_.RunOnce(); // Executes "remove_task(id2) @ T+10s".
+ ASSERT_EQ(2u, queue_.GetCount());
+ ASSERT_EQ(1u, task_runner_.GetTaskQueueSize());
+ EXPECT_EQ(id1, GetFirstCommandToBeRemoved());
+ task_runner_.RunOnce(); // Should remove task "id1" from queue.
+ ASSERT_EQ(1u, queue_.GetCount());
+ ASSERT_EQ(1u, task_runner_.GetTaskQueueSize());
+ EXPECT_EQ(id2, GetFirstCommandToBeRemoved());
+ task_runner_.RunOnce(); // Should remove task "id2" from queue.
+ EXPECT_EQ(0u, queue_.GetCount());
+ EXPECT_EQ(0u, task_runner_.GetTaskQueueSize());
+}
+
TEST_F(CommandQueueTest, Dispatch) {
FakeDispatcher dispatch(&queue_);
const std::string id1 = "id1";
diff --git a/src/component_manager_impl.cc b/src/component_manager_impl.cc
index 550775d..dec4a48 100644
--- a/src/component_manager_impl.cc
+++ b/src/component_manager_impl.cc
@@ -31,8 +31,10 @@ template <>
LIBWEAVE_EXPORT EnumToStringMap<UserRole>::EnumToStringMap()
: EnumToStringMap(kMap) {}
-ComponentManagerImpl::ComponentManagerImpl(base::Clock* clock)
- : clock_{clock ? clock : &default_clock_} {}
+ComponentManagerImpl::ComponentManagerImpl(provider::TaskRunner* task_runner,
+ base::Clock* clock)
+ : clock_{clock ? clock : &default_clock_},
+ command_queue_{task_runner, clock_} {}
ComponentManagerImpl::~ComponentManagerImpl() {}
diff --git a/src/component_manager_impl.h b/src/component_manager_impl.h
index 8c4ad16..f3c5451 100644
--- a/src/component_manager_impl.h
+++ b/src/component_manager_impl.h
@@ -15,7 +15,8 @@ namespace weave {
class ComponentManagerImpl final : public ComponentManager {
public:
- explicit ComponentManagerImpl(base::Clock* clock = nullptr);
+ explicit ComponentManagerImpl(provider::TaskRunner* task_runner,
+ base::Clock* clock = nullptr);
~ComponentManagerImpl() override;
// Loads trait definition schema.
diff --git a/src/component_manager_unittest.cc b/src/component_manager_unittest.cc
index 63fedac..97dc00d 100644
--- a/src/component_manager_unittest.cc
+++ b/src/component_manager_unittest.cc
@@ -7,6 +7,7 @@
#include <map>
#include <gtest/gtest.h>
+#include <weave/provider/test/fake_task_runner.h>
#include <weave/test/unittest_utils.h>
#include "src/bind_lambda.h"
@@ -90,8 +91,9 @@ class ComponentManagerTest : public ::testing::Test {
{"t5", "t6"}, nullptr));
}
+ StrictMock<provider::test::FakeTaskRunner> task_runner_;
StrictMock<test::MockClock> clock_;
- ComponentManagerImpl manager_{&clock_};
+ ComponentManagerImpl manager_{&task_runner_, &clock_};
};
} // anonymous namespace
diff --git a/src/config_unittest.cc b/src/config_unittest.cc
index fbb558a..4b0e5b4 100644
--- a/src/config_unittest.cc
+++ b/src/config_unittest.cc
@@ -68,7 +68,6 @@ TEST_F(ConfigTest, Defaults) {
EXPECT_FALSE(GetSettings().device_id.empty());
EXPECT_EQ("", GetSettings().firmware_version);
EXPECT_TRUE(GetSettings().wifi_auto_setup_enabled);
- EXPECT_FALSE(GetSettings().disable_security);
EXPECT_EQ("", GetSettings().test_privet_ssid);
EXPECT_EQ(std::set<PairingType>{PairingType::kPinCode},
GetSettings().pairing_modes);
@@ -164,8 +163,6 @@ TEST_F(ConfigTest, LoadState) {
EXPECT_EQ("state_device_id", GetSettings().device_id);
EXPECT_EQ(GetDefaultSettings().wifi_auto_setup_enabled,
GetSettings().wifi_auto_setup_enabled);
- EXPECT_EQ(GetDefaultSettings().disable_security,
- GetSettings().disable_security);
EXPECT_EQ(GetDefaultSettings().test_privet_ssid,
GetSettings().test_privet_ssid);
EXPECT_EQ(GetDefaultSettings().pairing_modes, GetSettings().pairing_modes);
diff --git a/src/device_manager.cc b/src/device_manager.cc
index 04d7a6b..097f854 100644
--- a/src/device_manager.cc
+++ b/src/device_manager.cc
@@ -29,7 +29,7 @@ DeviceManager::DeviceManager(provider::ConfigStore* config_store,
provider::Wifi* wifi,
provider::Bluetooth* bluetooth)
: config_{new Config{config_store}},
- component_manager_{new ComponentManagerImpl} {
+ component_manager_{new ComponentManagerImpl{task_runner}} {
if (http_server) {
auth_manager_.reset(new privet::AuthManager(
config_.get(), http_server->GetHttpsCertificateFingerprint()));
diff --git a/src/device_registration_info_unittest.cc b/src/device_registration_info_unittest.cc
index cd11ac9..7908c8b 100644
--- a/src/device_registration_info_unittest.cc
+++ b/src/device_registration_info_unittest.cc
@@ -208,7 +208,7 @@ class DeviceRegistrationInfoTest : public ::testing::Test {
{},
&clock_};
std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
- ComponentManagerImpl component_manager_;
+ ComponentManagerImpl component_manager_{&task_runner_};
};
TEST_F(DeviceRegistrationInfoTest, GetServiceURL) {
diff --git a/src/privet/privet_manager.cc b/src/privet/privet_manager.cc
index edc7907..9c717ce 100644
--- a/src/privet/privet_manager.cc
+++ b/src/privet/privet_manager.cc
@@ -53,8 +53,6 @@ void Manager::Start(Network* network,
CHECK(auth_manager);
CHECK(device);
- disable_security_ = device->GetSettings().disable_security;
-
device_ = DeviceDelegate::CreateDefault(
task_runner_, http_server->GetHttpPort(), http_server->GetHttpsPort(),
http_server->GetRequestTimeout());
@@ -129,9 +127,6 @@ void Manager::PrivetRequestHandlerWithData(
const std::shared_ptr<provider::HttpServer::Request>& request,
const std::string& data) {
std::string auth_header = request->GetFirstHeader(http::kAuthorization);
- if (auth_header.empty() && disable_security_)
- auth_header = "Privet anonymous";
-
base::DictionaryValue empty;
auto value = base::JSONReader::Read(data);
const base::DictionaryValue* dictionary = &empty;
diff --git a/src/privet/privet_manager.h b/src/privet/privet_manager.h
index 371d843..06eb89a 100644
--- a/src/privet/privet_manager.h
+++ b/src/privet/privet_manager.h
@@ -79,7 +79,6 @@ class Manager : public CloudDelegate::Observer {
void OnChanged();
void OnConnectivityChanged();
- bool disable_security_{false};
provider::TaskRunner* task_runner_{nullptr};
std::unique_ptr<CloudDelegate> cloud_;
std::unique_ptr<DeviceDelegate> device_;
diff --git a/src/privet/privet_types.cc b/src/privet/privet_types.cc
index dd291b3..9e50f94 100644
--- a/src/privet/privet_types.cc
+++ b/src/privet/privet_types.cc
@@ -52,7 +52,6 @@ const EnumToStringMap<WifiType>::Map kWifiTypeMap[] = {
};
const EnumToStringMap<CryptoType>::Map kCryptoTypeMap[] = {
- {CryptoType::kNone, "none"},
{CryptoType::kSpake_p224, "p224_spake2"},
};
diff --git a/src/privet/privet_types.h b/src/privet/privet_types.h
index c738865..49c4522 100644
--- a/src/privet/privet_types.h
+++ b/src/privet/privet_types.h
@@ -15,7 +15,6 @@ namespace weave {
namespace privet {
enum class CryptoType {
- kNone,
kSpake_p224,
};
diff --git a/src/privet/security_manager.cc b/src/privet/security_manager.cc
index 358876d..0f00699 100644
--- a/src/privet/security_manager.cc
+++ b/src/privet/security_manager.cc
@@ -67,25 +67,6 @@ class Spakep224Exchanger : public SecurityManager::KeyExchanger {
crypto::P224EncryptedKeyExchange spake_;
};
-class UnsecureKeyExchanger : public SecurityManager::KeyExchanger {
- public:
- explicit UnsecureKeyExchanger(const std::string& password)
- : password_(password) {}
- ~UnsecureKeyExchanger() override = default;
-
- // SecurityManager::KeyExchanger methods.
- const std::string& GetMessage() override { return password_; }
-
- bool ProcessMessage(const std::string& message, ErrorPtr* error) override {
- return true;
- }
-
- const std::string& GetKey() const override { return password_; }
-
- private:
- std::string password_;
-};
-
} // namespace
SecurityManager::SecurityManager(const Config* config,
@@ -218,8 +199,6 @@ std::set<PairingType> SecurityManager::GetPairingTypes() const {
std::set<CryptoType> SecurityManager::GetCryptoTypes() const {
std::set<CryptoType> result{CryptoType::kSpake_p224};
- if (GetSettings().disable_security)
- result.insert(CryptoType::kNone);
return result;
}
@@ -259,8 +238,6 @@ const Config::Settings& SecurityManager::GetSettings() const {
bool SecurityManager::IsValidPairingCode(
const std::vector<uint8_t>& auth_code) const {
- if (GetSettings().disable_security)
- return true;
for (const auto& session : confirmed_sessions_) {
const std::string& key = session.second->GetKey();
const std::string& id = session.first;
@@ -309,11 +286,6 @@ bool SecurityManager::StartPairing(PairingType mode,
case CryptoType::kSpake_p224:
spake.reset(new Spakep224Exchanger(code));
break;
- case CryptoType::kNone:
- if (GetSettings().disable_security) {
- spake.reset(new UnsecureKeyExchanger(code));
- break;
- }
// Fall through...
default:
return Error::AddTo(error, FROM_HERE, errors::kInvalidParams,
@@ -428,9 +400,6 @@ void SecurityManager::RegisterPairingListeners(
}
bool SecurityManager::CheckIfPairingAllowed(ErrorPtr* error) {
- if (GetSettings().disable_security)
- return true;
-
if (block_pairing_until_ > auth_manager_->Now()) {
return Error::AddTo(error, FROM_HERE, errors::kDeviceBusy,
"Too many pairing attempts");
diff --git a/src/privet/wifi_bootstrap_manager.cc b/src/privet/wifi_bootstrap_manager.cc
index 566da80..ce2016a 100644
--- a/src/privet/wifi_bootstrap_manager.cc
+++ b/src/privet/wifi_bootstrap_manager.cc
@@ -204,8 +204,12 @@ std::string WifiBootstrapManager::GetHostedSsid() const {
}
std::set<WifiType> WifiBootstrapManager::GetTypes() const {
- // TODO(wiley) This should do some system work to figure this out.
- return {WifiType::kWifi24};
+ std::set<WifiType> result;
+ if (wifi_->IsWifi24Supported())
+ result.insert(WifiType::kWifi24);
+ if (wifi_->IsWifi50Supported())
+ result.insert(WifiType::kWifi50);
+ return result;
}
void WifiBootstrapManager::OnConnectDone(const std::string& ssid,
@@ -255,9 +259,15 @@ void WifiBootstrapManager::OnMonitorTimeout() {
void WifiBootstrapManager::UpdateConnectionState() {
connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
-
Network::State service_state{network_->GetConnectionState()};
VLOG(3) << "New network state: " << EnumToString(service_state);
+
+ // TODO: Make it true wifi state, currently it's rather online state.
+ if (service_state != Network::State::kOnline &&
+ config_->GetSettings().last_configured_ssid.empty()) {
+ return;
+ }
+
switch (service_state) {
case Network::State::kOffline:
connection_state_ = ConnectionState{ConnectionState::kOffline};
diff --git a/src/privet/wifi_ssid_generator.cc b/src/privet/wifi_ssid_generator.cc
index 697e5d8..4ad1602 100644
--- a/src/privet/wifi_ssid_generator.cc
+++ b/src/privet/wifi_ssid_generator.cc
@@ -52,20 +52,27 @@ WifiSsidGenerator::WifiSsidGenerator(const CloudDelegate* cloud,
}
std::string WifiSsidGenerator::GenerateFlags() const {
- return GenerateFlagsInternal(false);
+ return GenerateFlagsInternal();
}
-std::string WifiSsidGenerator::GenerateFlagsInternal(bool for_ssid) const {
+std::string WifiSsidGenerator::GenerateFlagsInternal() const {
std::bitset<6> flags1;
// Device needs WiFi configuration.
flags1[0] = wifi_ && IsSetupNeeded(wifi_->GetConnectionState());
+
// Device needs GCD registration.
flags1[1] = IsSetupNeeded(gcd_->GetConnectionState());
std::bitset<6> flags2;
- // Device is discoverable over WiFi.
- flags2[0] = for_ssid || (wifi_ && !wifi_->GetHostedSsid().empty());
+ if (wifi_) {
+ std::set<WifiType> types = wifi_->GetTypes();
+ // Device supports 2.4Ghz WiFi networks.
+ flags2[0] = types.find(WifiType::kWifi24) != types.end();
+
+ // Device supports 5.0Ghz WiFi networks.
+ flags2[1] = types.find(WifiType::kWifi50) != types.end();
+ }
std::string result{2, base64chars[0]};
result[0] = base64chars[flags1.to_ulong()];
@@ -82,7 +89,7 @@ std::string WifiSsidGenerator::GenerateSsid() const {
std::string result =
base::StringPrintf(kSsidFormat, name.c_str(), idx.c_str(),
- model_id.c_str(), GenerateFlagsInternal(true).c_str());
+ model_id.c_str(), GenerateFlagsInternal().c_str());
CHECK_EQ(result[result.size() - 11], '.');
return result;
}
diff --git a/src/privet/wifi_ssid_generator.h b/src/privet/wifi_ssid_generator.h
index 2b86f28..1197e73 100644
--- a/src/privet/wifi_ssid_generator.h
+++ b/src/privet/wifi_ssid_generator.h
@@ -30,7 +30,7 @@ class WifiSsidGenerator final {
// Sets object to use |n| instead of random number for SSID generation.
void SetRandomForTests(int n);
- std::string GenerateFlagsInternal(bool for_ssid) const;
+ std::string GenerateFlagsInternal() const;
const CloudDelegate* gcd_{nullptr};
const WifiDelegate* wifi_{nullptr};
diff --git a/src/privet/wifi_ssid_generator_unittest.cc b/src/privet/wifi_ssid_generator_unittest.cc
index 10680c8..406576d 100644
--- a/src/privet/wifi_ssid_generator_unittest.cc
+++ b/src/privet/wifi_ssid_generator_unittest.cc
@@ -22,40 +22,44 @@ class WifiSsidGeneratorTest : public testing::Test {
WifiSsidGenerator ssid_generator_{&gcd_, &wifi_};
};
-TEST_F(WifiSsidGeneratorTest, GenerateFlagsNoHostedAp) {
+TEST_F(WifiSsidGeneratorTest, GenerateFlagsWithWifi24) {
+ EXPECT_CALL(wifi_, GetTypes())
+ .WillRepeatedly(Return(std::set<WifiType>{WifiType::kWifi24}));
+
EXPECT_EQ(ssid_generator_.GenerateFlags().size(), 2u);
wifi_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
gcd_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- EXPECT_EQ("DA", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("DB", ssid_generator_.GenerateFlags());
wifi_.connection_state_ = ConnectionState{ConnectionState::kOnline};
- EXPECT_EQ("CA", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("CB", ssid_generator_.GenerateFlags());
gcd_.connection_state_ = ConnectionState{ConnectionState::kOffline};
- EXPECT_EQ("AA", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("AB", ssid_generator_.GenerateFlags());
wifi_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- EXPECT_EQ("BA", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("BB", ssid_generator_.GenerateFlags());
}
-TEST_F(WifiSsidGeneratorTest, GenerateFlagsWithHostedAp) {
- EXPECT_CALL(wifi_, GetHostedSsid())
- .WillRepeatedly(Return(ssid_generator_.GenerateSsid()));
+TEST_F(WifiSsidGeneratorTest, GenerateFlagsWithWifi50) {
+ EXPECT_CALL(wifi_, GetTypes())
+ .WillRepeatedly(Return(std::set<WifiType>{WifiType::kWifi50}));
+
EXPECT_EQ(ssid_generator_.GenerateFlags().size(), 2u);
wifi_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
gcd_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- EXPECT_EQ("DB", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("DC", ssid_generator_.GenerateFlags());
wifi_.connection_state_ = ConnectionState{ConnectionState::kOnline};
- EXPECT_EQ("CB", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("CC", ssid_generator_.GenerateFlags());
gcd_.connection_state_ = ConnectionState{ConnectionState::kOffline};
- EXPECT_EQ("AB", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("AC", ssid_generator_.GenerateFlags());
wifi_.connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
- EXPECT_EQ("BB", ssid_generator_.GenerateFlags());
+ EXPECT_EQ("BC", ssid_generator_.GenerateFlags());
}
TEST_F(WifiSsidGeneratorTest, GenerateSsid31orLess) {
diff --git a/src/test/fake_task_runner.cc b/src/test/fake_task_runner.cc
index 88e078b..68d5e32 100644
--- a/src/test/fake_task_runner.cc
+++ b/src/test/fake_task_runner.cc
@@ -52,6 +52,10 @@ void FakeTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
queue_.emplace(std::make_pair(test_clock_->Now() + delay, ++counter_), task);
}
+size_t FakeTaskRunner::GetTaskQueueSize() const {
+ return queue_.size();
+}
+
} // namespace test
} // namespace provider
} // namespace weave
diff --git a/src/weave_unittest.cc b/src/weave_unittest.cc
index ebc66cd..b300f57 100644
--- a/src/weave_unittest.cc
+++ b/src/weave_unittest.cc
@@ -181,7 +181,10 @@ std::set<typename Map::key_type> GetKeys(const Map& map) {
class WeaveTest : public ::testing::Test {
protected:
- void SetUp() override {}
+ void SetUp() override {
+ EXPECT_CALL(wifi_, IsWifi24Supported()).WillRepeatedly(Return(true));
+ EXPECT_CALL(wifi_, IsWifi50Supported()).WillRepeatedly(Return(false));
+ }
template <class UrlMatcher>
void ExpectRequest(HttpClient::Method method,
diff --git a/third_party/get_libevent.sh b/third_party/get_libevent.sh
deleted file mode 100755
index 9985bc0..0000000
--- a/third_party/get_libevent.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-# 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.
-
-# Make libevent.
-# Example uses libevent to implement HTTPS server. This capability is
-# available only in version 2.1.x-alpha. Step could be replaced with apt-get
-# in future.
-cd $(dirname "$0")
-THIRD_PARTY=$(pwd)
-
-mkdir -p include lib
-
-rm -rf $THIRD_PARTY/libevent
-git clone https://github.com/libevent/libevent.git || exit 1
-cd libevent || exit 1
-
-./autogen.sh || exit 1
-./configure --disable-shared || exit 1
-make || 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/*.h include/event2 $THIRD_PARTY/include/ || exit 1
-cp -f .libs/lib* $THIRD_PARTY/lib/ || exit 1
-
-rm -rf $THIRD_PARTY/libevent
diff --git a/third_party/get_libevhtp.sh b/third_party/get_libevhtp.sh
new file mode 100755
index 0000000..c270813
--- /dev/null
+++ b/third_party/get_libevhtp.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2016 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.
+
+# Make libevhtp.
+# Example uses libevhtp to implement HTTPS server. This step could be
+# replaced with apt-get in future (Debian jessie, Ubuntu vivid).
+cd $(dirname "$0")
+THIRD_PARTY=$(pwd)
+
+mkdir -p include lib
+
+rm -rf $THIRD_PARTY/libevhtp
+curl -L https://github.com/ellzey/libevhtp/archive/1.2.10.tar.gz | tar xz || exit 1
+mv libevhtp-1.2.10 $THIRD_PARTY/libevhtp || exit 1
+cd $THIRD_PARTY/libevhtp || exit 1
+
+cmake -D EVHTP_DISABLE_REGEX:BOOL=ON . || exit 1
+make evhtp || exit 1
+
+cp -rf evhtp-config.h evhtp.h evthr/evthr.h htparse/htparse.h $THIRD_PARTY/include/ || exit 1
+cp -f libevhtp.a $THIRD_PARTY/lib/ || exit 1
+
+rm -rf $THIRD_PARTY/libevhtp
diff --git a/third_party/third_party.mk b/third_party/third_party.mk
index 8a11e2d..7f651a2 100644
--- a/third_party/third_party.mk
+++ b/third_party/third_party.mk
@@ -64,15 +64,15 @@ clean-gtest :
rm -rf third_party/googletest
###
-# libevent (third_party, downloaded on build)
-
-third_party/include/event2/event.h :
- @echo Downloading and building libevent...
- DISABLE_LIBEVENT_TEST=1 third_party/get_libevent.sh
- @echo Finished downloading and building libevent.
-
-clean-libevent :
- rm -rf third_party/include/ev* third_party/include/event2
- rm -rf third_party/lib/libevent*
- rm -rf third_party/libevent
-
+# libevhtp (third_party, downloaded on build)
+
+third_party/lib/libevhtp.a : third_party/include/evhtp.h
+third_party/include/evhtp.h :
+ @echo Downloading and building libevhtp...
+ third_party/get_libevhtp.sh
+ @echo Finished downloading and building libevhtp.
+
+clean-libevhtp :
+ rm -rf third_party/include/evhtp.h third_party/include/evhtp-config.h third_party/include/evthr.h third_party/include/htparse.h
+ rm -rf third_party/lib/libevhtp.a
+ rm -rf third_party/libevhtp