From cf14f7dc8a7329d31c88e77abde28488af462c1b Mon Sep 17 00:00:00 2001 From: Ingve Vormestrand Date: Thu, 22 Mar 2018 15:13:33 +0100 Subject: [PATCH 01/23] uplink: send tag --- lib/uplink/ws_uplink.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/uplink/ws_uplink.cpp b/lib/uplink/ws_uplink.cpp index abb2be903a..c51b001600 100644 --- a/lib/uplink/ws_uplink.cpp +++ b/lib/uplink/ws_uplink.cpp @@ -410,10 +410,10 @@ namespace uplink { writer.String(binary_hash_); } - if(not tag_.empty()) + if(not config_.tag.empty()) { writer.Key("tag"); - writer.String(tag_); + writer.String(config_.tag); } if(update_time_taken > 0) From 5da97a11c60e800ad4f7c70f2e2afc0d20ddbb7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Thu, 22 Mar 2018 15:39:51 +0100 Subject: [PATCH 02/23] util: isotime now checks return value and return empty str on fail (too big) #1721 --- api/util/isotime.hpp | 8 +++++--- test/util/unit/isotime.cpp | 13 ++++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/api/util/isotime.hpp b/api/util/isotime.hpp index 59b6b4bb49..93d0890527 100644 --- a/api/util/isotime.hpp +++ b/api/util/isotime.hpp @@ -28,15 +28,17 @@ struct isotime * @brief Returns a ISO 8601 UTC datetime string. * Example: 2017-04-10T13:37:00Z * + * @note Invalid time (too big for the format) will result in a empty string. + * * @param[in] ts A timestamp * * @return An ISO datetime string, formatted as "YYYY-MM-DDThh:mm:ssZ" */ static std::string to_datetime_string(time_t ts) { - char buf[sizeof "2017-04-10T13:37:00Z"]; - strftime(buf, sizeof buf, "%FT%TZ", gmtime(&ts)); - return buf; + char buf[sizeof("2017-04-10T13:337:00Z")]; + const auto res = std::strftime(buf, sizeof(buf)-1, "%FT%TZ", gmtime(&ts)); + return {buf, res}; } /** diff --git a/test/util/unit/isotime.cpp b/test/util/unit/isotime.cpp index 11f7794654..4fe9e2d57e 100644 --- a/test/util/unit/isotime.cpp +++ b/test/util/unit/isotime.cpp @@ -35,5 +35,16 @@ CASE("A timestamp can be converted into a ISO UTC datetime string") EXPECT(str == "1970-01-01T05:00:00Z"); - // Not gonna bother more due to leap seconds and calendars etc... + uint64_t big_number = 253402297200L; + + str = isotime::to_datetime_string(big_number); + + EXPECT(str == "9999-12-31T23:00:00Z"); + + uint64_t bigger_number = big_number + 2*60*60; + + str = isotime::to_datetime_string(bigger_number); + + // buffer is not big enough for more than 21 chars + EXPECT(str == ""); } From f1c7b90d849406a4a8414f1982861906eb28d43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Thu, 22 Mar 2018 15:43:17 +0100 Subject: [PATCH 03/23] test: Kinda fixed unittest building on macOS --- test/CMakeLists.txt | 11 ++++++++++- test/lest_util/stdlib.h | 7 +++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/lest_util/stdlib.h diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 453d700818..1db1f18439 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,6 +34,15 @@ endif() set(CMAKE_CXX_FLAGS "-g -O0 -march=native -std=c++17 -Wall -Wextra -Wno-unused-function -D__id_t_defined -DUNITTESTS -DURI_THROW_ON_ERROR ${NO_INFO} ${NO_DEBUG} -DGSL_THROW_ON_CONTRACT_VIOLATION -Dlest_FEATURE_AUTO_REGISTER=1 -DHAVE_LEST_MAIN") +if (APPLE) +message(STATUS "Including brew bundled libc++") +execute_process(COMMAND brew "--prefix" "llvm@5" OUTPUT_VARIABLE BREW_LLVM) +string(STRIP ${BREW_LLVM} BREW_LLVM) +set(BREW_LIBCXX_INC ${BREW_LLVM}/lib) +message(STATUS "Brew libc++ location: " ${BREW_LIBCXX_INC}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${BREW_LIBCXX_INC} -Wl") +endif() + if(NOT DEFINED ${INCLUDEOS_ROOT}) set(INCLUDEOS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..) endif() @@ -42,6 +51,7 @@ set(SRC ${INCLUDEOS_ROOT}/src) set(TEST ${INCLUDEOS_ROOT}/test) include_directories( + ${TEST}/lest_util ${INCLUDEOS_ROOT}/api ${INCLUDEOS_ROOT}/src/ ${INCLUDEOS_ROOT}/src/include @@ -49,7 +59,6 @@ include_directories( ${INCLUDEOS_ROOT}/mod/GSL ${INCLUDEOS_ROOT}/mod/uzlib/src ${TEST}/lest/include - ${TEST}/lest_util ) set(LEST_UTIL diff --git a/test/lest_util/stdlib.h b/test/lest_util/stdlib.h new file mode 100644 index 0000000000..f0e592f364 --- /dev/null +++ b/test/lest_util/stdlib.h @@ -0,0 +1,7 @@ +#pragma once +#include +#ifdef __MACH__ +void* aligned_alloc(size_t alignment, size_t size); +#endif + +#include_next From 37742083126759feb73e18e6835a0766c9a92c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Thu, 22 Mar 2018 15:44:55 +0100 Subject: [PATCH 04/23] bufstore: Replaced raw next ptr with unique, now using aligned_alloc --- api/net/buffer_store.hpp | 2 +- src/net/buffer_store.cpp | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/api/net/buffer_store.hpp b/api/net/buffer_store.hpp index 7117374263..e5e8e7b73d 100644 --- a/api/net/buffer_store.hpp +++ b/api/net/buffer_store.hpp @@ -93,7 +93,7 @@ namespace net size_t bufsize_; uint8_t* pool_; std::vector available_; - BufferStore* next_; + std::unique_ptr next_; int index; #ifndef INCLUDEOS_SINGLE_THREADED // has strict alignment reqs, so put at end diff --git a/src/net/buffer_store.cpp b/src/net/buffer_store.cpp index 180f5097ed..1e84ead4b6 100644 --- a/src/net/buffer_store.cpp +++ b/src/net/buffer_store.cpp @@ -15,12 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#if !defined(__MACH__) -#include -#else -#include -extern void *memalign(size_t, size_t); -#endif +#include #include #include #include @@ -64,7 +59,7 @@ namespace net { assert(bufsize != 0); const size_t DATA_SIZE = poolsize_; - this->pool_ = (uint8_t*) memalign(PAGE_SIZE, DATA_SIZE); + this->pool_ = (uint8_t*) aligned_alloc(PAGE_SIZE, DATA_SIZE); assert(this->pool_); available_.reserve(num); @@ -79,7 +74,7 @@ namespace net { } BufferStore::~BufferStore() { - delete this->next_; + this->next_ = nullptr; free(this->pool_); } @@ -89,7 +84,7 @@ namespace net { #ifdef ENABLE_BUFFERSTORE_CHAIN auto* parent = this; while (parent->next_ != nullptr) { - parent = parent->next_; + parent = parent->next_.get(); avail += parent->available_.size(); } #endif @@ -101,7 +96,7 @@ namespace net { #ifdef ENABLE_BUFFERSTORE_CHAIN auto* parent = this; while (parent->next_ != nullptr) { - parent = parent->next_; + parent = parent->next_.get(); total += parent->local_buffers(); } #endif @@ -113,13 +108,13 @@ namespace net { #ifdef ENABLE_BUFFERSTORE_CHAIN BufferStore* parent = this; while (parent->next_ != nullptr) { - parent = parent->next_; + parent = parent->next_.get(); if (!parent->available_.empty()) return parent; } BSD_BUF(" Allocating %lu new buffers (%lu total)\n", local_buffers(), total_buffers() + local_buffers()); - parent->next_ = new BufferStore(local_buffers(), bufsize()); - return parent->next_; + parent->next_ = std::make_unique(local_buffers(), bufsize()); + return parent->next_.get(); #else return nullptr; #endif @@ -170,14 +165,14 @@ namespace net { #endif #ifdef ENABLE_BUFFERSTORE_CHAIN // try to release buffer on linked bufferstore - BufferStore* ptr = next_; + BufferStore* ptr = next_.get(); while (ptr != nullptr) { if (ptr->is_from_this_pool(buff)) { BSD_RELEASE("released on other bufferstore\n"); ptr->release_directly(buff); return; } - ptr = ptr->next_; + ptr = ptr->next_.get(); } #endif throw std::runtime_error("Packet did not belong"); From d5933fc0bb081565411bb6a53861cc200a6ecbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Thu, 22 Mar 2018 16:10:10 +0100 Subject: [PATCH 05/23] util: Fixed silly mistake/misunderstanding in isotime --- api/util/isotime.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/util/isotime.hpp b/api/util/isotime.hpp index 93d0890527..a6d6fb9b16 100644 --- a/api/util/isotime.hpp +++ b/api/util/isotime.hpp @@ -36,8 +36,8 @@ struct isotime */ static std::string to_datetime_string(time_t ts) { - char buf[sizeof("2017-04-10T13:337:00Z")]; - const auto res = std::strftime(buf, sizeof(buf)-1, "%FT%TZ", gmtime(&ts)); + char buf[sizeof("2017-04-10T13:37:00Z")]; + const auto res = std::strftime(buf, sizeof(buf), "%FT%TZ", gmtime(&ts)); return {buf, res}; } From e7a7a281b3a1e17edc7deba95f916a6fa407785c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Thu, 22 Mar 2018 16:10:49 +0100 Subject: [PATCH 06/23] test: Silenced warning on mac --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1db1f18439..a02bd435ef 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -40,7 +40,7 @@ execute_process(COMMAND brew "--prefix" "llvm@5" OUTPUT_VARIABLE BREW_LLVM) string(STRIP ${BREW_LLVM} BREW_LLVM) set(BREW_LIBCXX_INC ${BREW_LLVM}/lib) message(STATUS "Brew libc++ location: " ${BREW_LIBCXX_INC}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${BREW_LIBCXX_INC} -Wl") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${BREW_LIBCXX_INC} -Wno-unused-command-line-argument") endif() if(NOT DEFINED ${INCLUDEOS_ROOT}) From 0f26f7bea1e0bdca49a9869435eb664684f66070 Mon Sep 17 00:00:00 2001 From: Nikhil AP Date: Fri, 23 Mar 2018 06:29:10 -0400 Subject: [PATCH 07/23] Fix the breakage of booting solo5 using '--with-solo5' option --- vmrunner/vmrunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vmrunner/vmrunner.py b/vmrunner/vmrunner.py index c1c52a5a43..bc30fcbd1e 100644 --- a/vmrunner/vmrunner.py +++ b/vmrunner/vmrunner.py @@ -224,7 +224,7 @@ def net_arg(self): def get_final_output(self): return self._proc.communicate() - def boot(self, multiboot, kernel_args = "", image_name = None): + def boot(self, multiboot, debug=False, kernel_args = "", image_name = None): self._stopped = False qkvm_bin = INCLUDEOS_HOME + "/includeos/x86_64/lib/ukvm-bin" From 08afd8a9e72e6ae0418b4d7378f79764d5fb9816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Fri, 23 Mar 2018 15:13:45 +0100 Subject: [PATCH 08/23] util: URI now using vector as storage (can be safely moved) --- api/util/uri.hpp | 5 +++-- src/util/uri.cpp | 34 +++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/api/util/uri.hpp b/api/util/uri.hpp index dec93eb8eb..1956cc99de 100644 --- a/api/util/uri.hpp +++ b/api/util/uri.hpp @@ -19,6 +19,7 @@ #ifndef UTIL_URI_HPP #define UTIL_URI_HPP +#include #include #include @@ -252,7 +253,7 @@ class URI { /// /// @return A string representation of this class /// - const std::string& to_string() const noexcept; + std::string to_string() const; /// /// Operator to transform this class into string form @@ -285,7 +286,7 @@ class URI { /// /// A copy of the data representing a uri /// - std::string uri_str_; + std::vector uri_str_; uint16_t port_ {0xFFFF}; diff --git a/src/util/uri.cpp b/src/util/uri.cpp index 6941f035c6..53f0efbbec 100644 --- a/src/util/uri.cpp +++ b/src/util/uri.cpp @@ -26,6 +26,12 @@ namespace uri { +static inline std::vector decoded_vector(util::csview input) +{ + auto res = decode(input); + return {res.begin(), res.end()}; +} + /////////////////////////////////////////////////////////////////////////////// static inline bool icase_equal(util::csview lhs, util::csview rhs) noexcept { return (lhs.size() == rhs.size()) @@ -67,37 +73,37 @@ static inline uint16_t bind_port(util::csview scheme, const uint16_t port_from_u /////////////////////////////////////////////////////////////////////////////// // copy helper /////////////////////////////////////////////////////////////////////////////// -static inline util::sview updated_copy(const std::string& to_copy, +static inline util::sview updated_copy(const std::vector& to_copy, util::csview view, - const std::string& from_copy) + const std::vector& from_copy) { return {to_copy.data() + (view.data() - from_copy.data()), view.size()}; } /////////////////////////////////////////////////////////////////////////////// URI::URI(const char* uri, const bool parse) - : uri_str_{decode(uri)} + : uri_str_{decoded_vector(uri)} { if (parse) this->parse(); } /////////////////////////////////////////////////////////////////////////////// URI::URI(const char* uri, const size_t count, const bool parse) - : uri_str_{decode(util::csview{uri, count})} + : uri_str_{decoded_vector(util::csview{uri, count})} { if (parse) this->parse(); } /////////////////////////////////////////////////////////////////////////////// URI::URI(const std::string& uri, const bool parse) - : uri_str_{decode(util::csview{uri.data(), uri.length()})} + : uri_str_{decoded_vector(util::csview{uri.data(), uri.length()})} { if (parse) this->parse(); } /////////////////////////////////////////////////////////////////////////////// URI::URI(util::csview uri, const bool parse) - : uri_str_{decode(uri)} + : uri_str_{decoded_vector(uri)} { if (parse) this->parse(); } @@ -134,7 +140,8 @@ URI::URI(URI&& u) noexcept , query_ {u.query_} , fragment_ {u.fragment_} , query_map_{std::move(u.query_map_)} -{} +{ +} /////////////////////////////////////////////////////////////////////////////// URI& URI::operator=(const URI& u) { @@ -251,18 +258,18 @@ URI::operator bool() const noexcept { } /////////////////////////////////////////////////////////////////////////////// -const std::string& URI::to_string() const noexcept { - return uri_str_; +std::string URI::to_string() const { + return {uri_str_.begin(), uri_str_.end()}; } /////////////////////////////////////////////////////////////////////////////// URI::operator std::string () const { - return uri_str_; + return to_string(); } /////////////////////////////////////////////////////////////////////////////// URI& URI::operator << (const std::string& chunk) { - uri_str_.append(chunk); + uri_str_.insert(uri_str_.end(), chunk.begin(), chunk.end()); return *this; } @@ -272,11 +279,12 @@ URI& URI::parse() { http_parser_url_init(&u); const auto p = uri_str_.data(); - const auto result = http_parser_parse_url(p, uri_str_.length(), 0, &u); + const auto result = http_parser_parse_url(p, uri_str_.size(), 0, &u); #ifdef URI_THROW_ON_ERROR if (result not_eq 0) { - throw URI_error{"Invalid uri: " + uri_str_}; + std::string uri{uri_str_.begin(), uri_str_.end()}; + throw URI_error{"Invalid uri: " + uri}; } #endif //< URI_THROW_ON_ERROR From 7a35014024900baa5f85aadde88a21e271e0f507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Fri, 23 Mar 2018 15:18:57 +0100 Subject: [PATCH 09/23] http: Client API now supports security flag (if to use HTTPS) --- api/net/http/client.hpp | 61 +++++++++++++++++++------- src/net/http/client.cpp | 63 ++++++++++++++++++++------- test/net/integration/http/service.cpp | 15 ++++++- 3 files changed, 106 insertions(+), 33 deletions(-) diff --git a/api/net/http/client.hpp b/api/net/http/client.hpp index d3ac1aa379..1c0d3c7c62 100644 --- a/api/net/http/client.hpp +++ b/api/net/http/client.hpp @@ -28,6 +28,10 @@ namespace http { + struct Client_error : public std::runtime_error { + using runtime_error::runtime_error; + }; + using Response_handler = Client_connection::Response_handler; class Client { @@ -67,7 +71,7 @@ namespace http { }; private: - using ResolveCallback = delegate; + using ResolveCallback = delegate; public: explicit Client(TCP& tcp, Request_handler on_send = nullptr); @@ -88,7 +92,8 @@ namespace http { * @param[in] host The host * @param[in] cb Callback to be invoked when a response is received (or error) */ - void send(Request_ptr req, Host host, Response_handler cb, Options options = {}); + void send(Request_ptr req, Host host, Response_handler cb, + const bool secure = false, Options options = {}); /** * @brief Create a request on the given URL @@ -98,12 +103,14 @@ namespace http { * @param[in] hfields A set of headers * @param[in] cb Response handler */ - void request(Method method, URI url, Header_set hfields, Response_handler cb, Options options = {}); + void request(Method method, URI url, Header_set hfields, + Response_handler cb, Options options = {}); /** * @brief Same as above */ - void request(Method method, std::string url, Header_set hfields, Response_handler cb, Options options = {}) + void request(Method method, std::string url, Header_set hfields, + Response_handler cb, Options options = {}) { request(method, URI{url}, std::move(hfields), std::move(cb), std::move(options)); } /** @@ -115,7 +122,8 @@ namespace http { * @param[in] hfields A set of headers * @param[in] cb Response handler */ - void request(Method method, Host host, std::string path, Header_set hfields, Response_handler cb, Options options = {}); + void request(Method method, Host host, std::string path, Header_set hfields, + Response_handler cb, const bool secure = false, Options options = {}); /** * @brief Create a request on the given URL with payload @@ -126,12 +134,14 @@ namespace http { * @param[in] data The data (payload) * @param[in] cb Response handler */ - void request(Method method, URI url, Header_set hfields, std::string data, Response_handler cb, Options options = {}); + void request(Method method, URI url, Header_set hfields, std::string data, + Response_handler cb, Options options = {}); /** * @brief Same as above */ - void request(Method method, std::string url, Header_set hfields, std::string data, Response_handler cb, Options options = {}) + void request(Method method, std::string url, Header_set hfields, std::string data, + Response_handler cb, Options options = {}) { request(method, URI{url}, std::move(hfields), std::move(data), std::move(cb), std::move(options)); } /** @@ -144,15 +154,21 @@ namespace http { * @param[in] data The data (payload) * @param[in] cb Response handler */ - void request(Method method, Host host, std::string path, Header_set hfields, const std::string& data, Response_handler cb, Options options = {}); + void request(Method method, Host host, std::string path, Header_set hfields, + const std::string& data, Response_handler cb, + const bool secure = false, Options options = {}); /* GET */ inline void get(URI url, Header_set hfields, Response_handler cb, Options options = {}); - inline void get(Host host, std::string path, Header_set hfields, Response_handler cb, Options options = {}); + inline void get(Host host, std::string path, Header_set hfields, + Response_handler cb, const bool secure = false, Options options = {}); /* POST */ - inline void post(URI url, Header_set hfields, std::string data, Response_handler cb, Options options = {}); - inline void post(Host host, std::string path, Header_set hfields, const std::string& data, Response_handler cb, Options options = {}); + inline void post(URI url, Header_set hfields, std::string data, + Response_handler cb, Options options = {}); + inline void post(Host host, std::string path, Header_set hfields, + const std::string& data, Response_handler cb, + const bool secure = false, Options options = {}); /** * @brief Set callback to be invoked right before the request gets sent. @@ -180,6 +196,7 @@ namespace http { Request_handler on_send_; Connection_mapset conns_; bool keep_alive_ = false; + const bool supports_https = false; void resolve(const std::string& host, ResolveCallback); @@ -197,8 +214,16 @@ namespace http { Client_connection& get_connection(const Host host); + virtual Client_connection& get_secure_connection(const Host host); + void close(Client_connection&); + void validate_secure(const bool secure) const + { + if(secure and not this->supports_https) + throw Client_error{"Secured connections not supported (use the HTTPS Client)."}; + } + }; // < class Client @@ -206,15 +231,19 @@ namespace http { inline void Client::get(URI url, Header_set hfields, Response_handler cb, Options options) { request(GET, std::move(url), std::move(hfields), std::move(cb), std::move(options)); } - inline void Client::get(Host host, std::string path, Header_set hfields, Response_handler cb, Options options) - { request(GET, std::move(host), std::move(path), std::move(hfields), std::move(cb), std::move(options)); } + inline void Client::get(Host host, std::string path, Header_set hfields, + Response_handler cb, const bool secure, Options options) + { request(GET, std::move(host), std::move(path), std::move(hfields), std::move(cb), secure, std::move(options)); } /* POST */ - inline void Client::post(URI url, Header_set hfields, std::string data, Response_handler cb, Options options) + inline void Client::post(URI url, Header_set hfields, std::string data, + Response_handler cb, Options options) { request(POST, std::move(url), std::move(hfields), std::move(data), std::move(cb), std::move(options)); } - inline void Client::post(Host host, std::string path, Header_set hfields, const std::string& data, Response_handler cb, Options options) - { request(POST, std::move(host), std::move(path), std::move(hfields), std::move(data), std::move(cb), std::move(options)); } + inline void Client::post(Host host, std::string path, Header_set hfields, + const std::string& data, Response_handler cb, + const bool secure, Options options) + { request(POST, std::move(host), std::move(path), std::move(hfields), std::move(data), std::move(cb), secure, std::move(options)); } } // < namespace http diff --git a/src/net/http/client.cpp b/src/net/http/client.cpp index aacc1d553f..e77b2a1630 100644 --- a/src/net/http/client.cpp +++ b/src/net/http/client.cpp @@ -34,17 +34,19 @@ namespace http { req->set_method(method); auto& header = req->header(); - header.set_field(header::User_Agent, "IncludeOS/0.10"); + header.set_field(header::User_Agent, "IncludeOS/0.12"); set_connection_header(*req); return req; } - void Client::send(Request_ptr req, Host host, Response_handler cb, Options options) + void Client::send(Request_ptr req, Host host, Response_handler cb, + const bool secure, Options options) { Expects(cb != nullptr); using namespace std; - auto& conn = get_connection(host); + auto& conn = (not secure) ? + get_connection(host) : get_secure_connection(host); auto&& header = req->header(); @@ -64,9 +66,15 @@ namespace http { conn.send(move(req), move(cb), options.bufsize, options.timeout); } - void Client::request(Method method, URI url, Header_set hfields, Response_handler cb, Options options) + void Client::request(Method method, URI url, Header_set hfields, + Response_handler cb, Options options) { Expects(cb != nullptr); + + // find out if this is a secured request or not + const bool secure = (url.scheme() == "https"); + validate_secure(secure); + using namespace std; if (url.host_is_ip4()) @@ -83,7 +91,7 @@ namespace http { // Default to port 80 if non given const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80; - send(move(req), {ip, port}, move(cb), move(options)); + send(move(req), {ip, port}, move(cb), secure, move(options)); } else { @@ -95,7 +103,8 @@ namespace http { url{move(url)}, hfields{move(hfields)}, cb{move(cb)}, - opt{move(options)} + opt{move(options)}, + secure ] (net::ip4::Addr ip, const net::Error&) { @@ -112,7 +121,7 @@ namespace http { // Default to port 80 if non given const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80; - send(move(req), {ip, port}, move(cb), move(opt)); + send(move(req), {ip, port}, move(cb), secure, move(opt)); } else { @@ -122,8 +131,12 @@ namespace http { } } - void Client::request(Method method, Host host, std::string path, Header_set hfields, Response_handler cb, Options options) + void Client::request(Method method, Host host, std::string path, + Header_set hfields, Response_handler cb, + const bool secure, Options options) { + validate_secure(secure); + using namespace std; // setup request with method and headers auto req = create_request(method); @@ -132,11 +145,17 @@ namespace http { //set uri (default "/") req->set_uri((!path.empty()) ? URI{move(path)} : URI{"/"}); - send(move(req), move(host), move(cb), move(options)); + send(move(req), move(host), move(cb), secure, move(options)); } - void Client::request(Method method, URI url, Header_set hfields, std::string data, Response_handler cb, Options options) + void Client::request(Method method, URI url, Header_set hfields, + std::string data, Response_handler cb, + Options options) { + // find out if this is a secured request or not + const bool secure = (url.scheme() == "https"); + validate_secure(secure); + using namespace std; if (url.host_is_ip4()) { @@ -155,7 +174,7 @@ namespace http { // Default to port 80 if non given const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80; - send(move(req), {ip, port}, move(cb), move(options)); + send(move(req), {ip, port}, move(cb), secure, move(options)); } else { @@ -169,7 +188,8 @@ namespace http { hfields{move(hfields)}, data{move(data)}, cb{move(cb)}, - opt{move(options)} + opt{move(options)}, + secure ] (auto ip, const net::Error&) { // Host resolved @@ -188,7 +208,7 @@ namespace http { // Default to port 80 if non given const uint16_t port = (url.port() != 0xFFFF) ? url.port() : 80; - this->send(move(req), {ip, port}, move(cb), move(opt)); + this->send(move(req), {ip, port}, move(cb), secure, move(opt)); } else { @@ -199,8 +219,12 @@ namespace http { } } - void Client::request(Method method, Host host, std::string path, Header_set hfields, const std::string& data, Response_handler cb, Options options) + void Client::request(Method method, Host host, std::string path, + Header_set hfields, const std::string& data, + Response_handler cb, const bool secure, Options options) { + validate_secure(secure); + using namespace std; // setup request with method and headers auto req = create_request(method); @@ -212,7 +236,7 @@ namespace http { // Add data and content length add_data(*req, data); - send(move(req), move(host), move(cb), move(options)); + send(move(req), move(host), move(cb), secure, move(options)); } void Client::add_data(Request& req, const std::string& data) @@ -260,10 +284,17 @@ namespace http { } // no non-occupied connections, emplace a new one - cset.push_back(std::make_unique(*this, std::make_unique(tcp_.connect(host)))); + cset.push_back(std::make_unique( + *this, std::make_unique(tcp_.connect(host))) + ); return *cset.back(); } + Client_connection& Client::get_secure_connection(const Host) + { + throw Client_error{"Secured connections not supported (use the HTTPS Client)."}; + } + void Client::close(Client_connection& c) { debug(" Closing %u:%s %p\n", c.local_port(), c.peer().to_string().c_str(), &c); diff --git a/test/net/integration/http/service.cpp b/test/net/integration/http/service.cpp index edf66fe5f0..370dd16254 100644 --- a/test/net/integration/http/service.cpp +++ b/test/net/integration/http/service.cpp @@ -75,8 +75,8 @@ void Service::ready() if (err) printf("Error: %s \n", err.to_string().c_str()); - printf("Received body: %s\n", res->body()); CHECKSERT(!err, "No error"); + printf("Received body: %s\n", res->body()); CHECKSERT(res->body() == "/testing", "Received body: \"/testing\""); using namespace std::chrono; // zzz... @@ -107,4 +107,17 @@ void Service::ready() printf("Response:\n%s\n", res->to_string().c_str()); }, { 3s }); + + INFO("Client", "HTTPS"); + + try + { + client_->get("https://www.google.com", {}, [](Error err, Response_ptr res, Connection&) {}); + assert(false && "Client should throw exception"); + } + catch(const http::Client_error& err) + { + CHECKSERT(true, "HTTP Client should throw exception on https URL"); + } + } From 8a77d9d768640b93ac39dec95d8b8df6349edddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Mon, 26 Mar 2018 15:20:41 +0200 Subject: [PATCH 10/23] tcp: Avoid deferencing pointer in Stream connect --- api/net/tcp/connection.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/net/tcp/connection.hpp b/api/net/tcp/connection.hpp index 3150024afc..17df50b1ef 100644 --- a/api/net/tcp/connection.hpp +++ b/api/net/tcp/connection.hpp @@ -235,8 +235,8 @@ class Connection { virtual void on_connect(ConnectCallback cb) override { tcp->on_connect(Connection::ConnectCallback::make_packed( - [this, cb] (Connection_ptr) - { cb(*this); })); + [this, cb] (Connection_ptr conn) + { if(conn) cb(*this); })); } /** From 3f6205106ebcd5d15e1c7838f95f6131520c813b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Mon, 26 Mar 2018 15:21:50 +0200 Subject: [PATCH 11/23] http: Wait for stream being connected before sending request --- src/net/http/client_connection.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/net/http/client_connection.cpp b/src/net/http/client_connection.cpp index 13ede9b478..1e0e9bf9cd 100644 --- a/src/net/http/client_connection.cpp +++ b/src/net/http/client_connection.cpp @@ -17,7 +17,6 @@ #include #include -#include namespace http { @@ -45,7 +44,17 @@ namespace http { if(timeout_dur_ > timeout_duration::zero()) timer_.restart(timeout_dur_); - send_request(bufsize); + // if the stream is not established, send the request when connected + if(not stream_->is_connected()) + { + stream_->on_connect([this, bufsize](auto&) + { + this->send_request(bufsize); + }); + } + else { + send_request(bufsize); + } } void Client_connection::send_request(const size_t bufsize) @@ -111,8 +120,8 @@ namespace http { { const unsigned conlen = std::stoul(std::string(header.value(header::Content_Length))); const unsigned body_size = res_->body().size(); - debug2(" [%s] Data: %u ConLen: %u Body:%u\n", - req_->uri().to_string().to_string().c_str(), data.size(), conlen, body_size); + //printf(" [%s] Data: %u ConLen: %u Body:%u\n", + // req_->uri().to_string().to_string().c_str(), data.size(), conlen, body_size); // risk buffering forever if no timeout if(body_size == conlen) { From 8d917bc8b7f21c7b274af1fd2fd1a5c1905498c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Mon, 26 Mar 2018 15:23:22 +0200 Subject: [PATCH 12/23] http: Make Client extendable --- api/net/http/client.hpp | 17 +++++++++++------ src/net/http/client.cpp | 7 ++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/api/net/http/client.hpp b/api/net/http/client.hpp index 1c0d3c7c62..3173ba370f 100644 --- a/api/net/http/client.hpp +++ b/api/net/http/client.hpp @@ -189,14 +189,21 @@ namespace http { std::string origin() const { return tcp_.stack().ip_addr().to_string(); } - private: - friend class Client_connection; + virtual ~Client() = default; + protected: TCP& tcp_; - Request_handler on_send_; Connection_mapset conns_; + + explicit Client(TCP& tcp, Request_handler on_send, const bool https_supported); + + virtual Client_connection& get_secure_connection(const Host host); + + private: + friend class Client_connection; + Request_handler on_send_; bool keep_alive_ = false; - const bool supports_https = false; + const bool supports_https; void resolve(const std::string& host, ResolveCallback); @@ -214,8 +221,6 @@ namespace http { Client_connection& get_connection(const Host host); - virtual Client_connection& get_secure_connection(const Host host); - void close(Client_connection&); void validate_secure(const bool secure) const diff --git a/src/net/http/client.cpp b/src/net/http/client.cpp index e77b2a1630..67869bb2ee 100644 --- a/src/net/http/client.cpp +++ b/src/net/http/client.cpp @@ -22,9 +22,14 @@ namespace http { const Client::timeout_duration Client::DEFAULT_TIMEOUT{std::chrono::seconds(5)}; Client::Client(TCP& tcp, Request_handler on_send) + : Client(tcp, std::move(on_send), false) + { + } + + Client::Client(TCP& tcp, Request_handler on_send, const bool https_supported) : tcp_(tcp), on_send_{std::move(on_send)}, - conns_{} + supports_https(https_supported) { } From b8829b13e139773c496cc8c63c950b336f2577aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Mon, 26 Mar 2018 15:55:20 +0200 Subject: [PATCH 13/23] http: Renamed Client to Basic_client --- api/net/http/{client.hpp => basic_client.hpp} | 26 ++++++------- api/net/http/client_connection.hpp | 6 +-- api/net/ws/websocket.hpp | 6 +-- lib/mender/include/mender/client.hpp | 4 +- lib/mender/src/client.cpp | 4 +- lib/uplink/ws_uplink.cpp | 6 +-- lib/uplink/ws_uplink.hpp | 6 +-- src/CMakeLists.txt | 2 +- src/net/http/{client.cpp => basic_client.cpp} | 38 +++++++++---------- src/net/http/client_connection.cpp | 4 +- src/net/ws/websocket.cpp | 10 ++--- test/net/integration/http/service.cpp | 18 ++++----- 12 files changed, 65 insertions(+), 65 deletions(-) rename api/net/http/{client.hpp => basic_client.hpp} (91%) rename src/net/http/{client.cpp => basic_client.cpp} (85%) diff --git a/api/net/http/client.hpp b/api/net/http/basic_client.hpp similarity index 91% rename from api/net/http/client.hpp rename to api/net/http/basic_client.hpp index 3173ba370f..a8f3e35594 100644 --- a/api/net/http/client.hpp +++ b/api/net/http/basic_client.hpp @@ -16,8 +16,8 @@ // limitations under the License. #pragma once -#ifndef HTTP_CLIENT_HPP -#define HTTP_CLIENT_HPP +#ifndef HTTP_BASIC_CLIENT_HPP +#define HTTP_BASIC_CLIENT_HPP // http #include "client_connection.hpp" @@ -34,7 +34,7 @@ namespace http { using Response_handler = Client_connection::Response_handler; - class Client { + class Basic_client { public: using TCP = net::TCP; using Host = net::Socket; @@ -74,7 +74,7 @@ namespace http { using ResolveCallback = delegate; public: - explicit Client(TCP& tcp, Request_handler on_send = nullptr); + explicit Basic_client(TCP& tcp, Request_handler on_send = nullptr); /** * @brief Creates a request with some predefined attributes @@ -189,13 +189,13 @@ namespace http { std::string origin() const { return tcp_.stack().ip_addr().to_string(); } - virtual ~Client() = default; + virtual ~Basic_client() = default; protected: TCP& tcp_; Connection_mapset conns_; - explicit Client(TCP& tcp, Request_handler on_send, const bool https_supported); + explicit Basic_client(TCP& tcp, Request_handler on_send, const bool https_supported); virtual Client_connection& get_secure_connection(const Host host); @@ -226,26 +226,26 @@ namespace http { void validate_secure(const bool secure) const { if(secure and not this->supports_https) - throw Client_error{"Secured connections not supported (use the HTTPS Client)."}; + throw Client_error{"Secured connections not supported with Basic_client (use the HTTPS Client)."}; } - }; // < class Client + }; // < class Basic_client /* Inline implementation */ - inline void Client::get(URI url, Header_set hfields, Response_handler cb, Options options) + inline void Basic_client::get(URI url, Header_set hfields, Response_handler cb, Options options) { request(GET, std::move(url), std::move(hfields), std::move(cb), std::move(options)); } - inline void Client::get(Host host, std::string path, Header_set hfields, + inline void Basic_client::get(Host host, std::string path, Header_set hfields, Response_handler cb, const bool secure, Options options) { request(GET, std::move(host), std::move(path), std::move(hfields), std::move(cb), secure, std::move(options)); } /* POST */ - inline void Client::post(URI url, Header_set hfields, std::string data, + inline void Basic_client::post(URI url, Header_set hfields, std::string data, Response_handler cb, Options options) { request(POST, std::move(url), std::move(hfields), std::move(data), std::move(cb), std::move(options)); } - inline void Client::post(Host host, std::string path, Header_set hfields, + inline void Basic_client::post(Host host, std::string path, Header_set hfields, const std::string& data, Response_handler cb, const bool secure, Options options) { request(POST, std::move(host), std::move(path), std::move(hfields), std::move(data), std::move(cb), secure, std::move(options)); } @@ -253,4 +253,4 @@ namespace http { } // < namespace http -#endif // < HTTP_CLIENT_HPP +#endif // < HTTP_BASIC_CLIENT_HPP diff --git a/api/net/http/client_connection.hpp b/api/net/http/client_connection.hpp index 2c03424c8e..3345ef052a 100644 --- a/api/net/http/client_connection.hpp +++ b/api/net/http/client_connection.hpp @@ -28,7 +28,7 @@ namespace http { - class Client; + class Basic_client; class Client_connection : public Connection { public: @@ -36,7 +36,7 @@ namespace http { using timeout_duration = std::chrono::milliseconds; public: - explicit Client_connection(Client&, Stream_ptr); + explicit Client_connection(Basic_client&, Stream_ptr); bool available() const { return on_response_ == nullptr && keep_alive_; } @@ -47,7 +47,7 @@ namespace http { void send(Request_ptr, Response_handler, const size_t bufsize, timeout_duration = timeout_duration::zero()); private: - Client& client_; + Basic_client& client_; Request_ptr req_; Response_ptr res_; Response_handler on_response_; diff --git a/api/net/ws/websocket.hpp b/api/net/ws/websocket.hpp index c020275589..14797d3677 100644 --- a/api/net/ws/websocket.hpp +++ b/api/net/ws/websocket.hpp @@ -22,7 +22,7 @@ #include "header.hpp" #include -#include +#include #include #include #include @@ -178,7 +178,7 @@ class WebSocket { * @param[in] dest The destination * @param[in] callback The connect callback */ - static void connect(http::Client& client, + static void connect(http::Basic_client& client, uri::URI dest, Connect_handler callback); @@ -202,7 +202,7 @@ class WebSocket { * * @return A Response handler for a http::Client */ - static http::Client::Response_handler + static http::Basic_client::Response_handler create_response_handler(Connect_handler on_connect, std::string key); void write(const char* buffer, size_t len, op_code = op_code::TEXT); diff --git a/lib/mender/include/mender/client.hpp b/lib/mender/include/mender/client.hpp index 013224b27b..03ec0fc86f 100644 --- a/lib/mender/include/mender/client.hpp +++ b/lib/mender/include/mender/client.hpp @@ -23,7 +23,7 @@ #include "auth_manager.hpp" #include #include -#include +#include #include #include "state.hpp" #include "device.hpp" @@ -110,7 +110,7 @@ namespace mender { // http related const std::string server_; net::Socket cached_; - std::unique_ptr httpclient_; + std::unique_ptr httpclient_; // state related friend class state::State; diff --git a/lib/mender/src/client.cpp b/lib/mender/src/client.cpp index d13521a32d..494ccbdd6f 100644 --- a/lib/mender/src/client.cpp +++ b/lib/mender/src/client.cpp @@ -29,7 +29,7 @@ namespace mender { device_{std::forward(dev)}, server_(server), cached_{0, port}, - httpclient_{std::make_unique(tcp)}, + httpclient_{std::make_unique(tcp)}, state_(&state::Init::instance()), context_({this, &Client::run_state}), on_state_store_(nullptr), @@ -44,7 +44,7 @@ namespace mender { device_{std::forward(dev)}, server_{socket.address().to_string()}, cached_(std::move(socket)), - httpclient_{std::make_unique(tcp)}, + httpclient_{std::make_unique(tcp)}, state_(&state::Init::instance()), context_({this, &Client::run_state}), on_state_store_(nullptr), diff --git a/lib/uplink/ws_uplink.cpp b/lib/uplink/ws_uplink.cpp index abb2be903a..64288769a1 100644 --- a/lib/uplink/ws_uplink.cpp +++ b/lib/uplink/ws_uplink.cpp @@ -90,8 +90,8 @@ namespace uplink { Expects(inet.ip_addr() != 0 && "Network interface not configured"); Expects(not config_.url.empty()); - client_ = std::make_unique(inet.tcp(), - http::Client::Request_handler{this, &WS_uplink::inject_token}); + client_ = std::make_unique(inet.tcp(), + http::Basic_client::Request_handler{this, &WS_uplink::inject_token}); auth(); } @@ -134,7 +134,7 @@ namespace uplink { { {"Content-Type", "application/json"} }, auth_data(), {this, &WS_uplink::handle_auth_response}, - http::Client::Options{15s}); + http::Basic_client::Options{15s}); } void WS_uplink::handle_auth_response(http::Error err, http::Response_ptr res, http::Connection&) diff --git a/lib/uplink/ws_uplink.hpp b/lib/uplink/ws_uplink.hpp index 3d30aaa7f7..b6369d6bac 100644 --- a/lib/uplink/ws_uplink.hpp +++ b/lib/uplink/ws_uplink.hpp @@ -23,7 +23,7 @@ #include "config.hpp" #include -#include +#include #include #include #include @@ -70,7 +70,7 @@ class WS_uplink { Config config_; net::Inet& inet_; - std::unique_ptr client_; + std::unique_ptr client_; net::WebSocket_ptr ws_; std::string id_; std::string token_; @@ -94,7 +94,7 @@ class WS_uplink { RTC::timestamp_t update_time_taken = 0; - void inject_token(http::Request& req, http::Client::Options&, const http::Client::Host) + void inject_token(http::Request& req, http::Basic_client::Options&, const http::Basic_client::Host) { if (not token_.empty()) req.header().add_field("Authorization", "Bearer " + token_); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a29d96b94b..5f633b3a51 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,7 +53,7 @@ set(OS_OBJECTS net/http/header.cpp net/http/header_fields.cpp net/http/message.cpp net/http/request.cpp net/http/response.cpp net/http/status_codes.cpp net/http/time.cpp net/http/version.cpp net/http/mime_types.cpp net/http/cookie.cpp - net/http/client_connection.cpp net/http/client.cpp + net/http/client_connection.cpp net/http/basic_client.cpp net/http/server_connection.cpp net/http/server.cpp net/http/response_writer.cpp net/ws/websocket.cpp ${OPENSSL_MODULES} ${BOTAN_MODULES} net/nat/nat.cpp net/nat/napt.cpp diff --git a/src/net/http/client.cpp b/src/net/http/basic_client.cpp similarity index 85% rename from src/net/http/client.cpp rename to src/net/http/basic_client.cpp index 67869bb2ee..b6caa39852 100644 --- a/src/net/http/client.cpp +++ b/src/net/http/basic_client.cpp @@ -15,25 +15,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include namespace http { - const Client::timeout_duration Client::DEFAULT_TIMEOUT{std::chrono::seconds(5)}; + const Basic_client::timeout_duration Basic_client::DEFAULT_TIMEOUT{std::chrono::seconds(5)}; - Client::Client(TCP& tcp, Request_handler on_send) - : Client(tcp, std::move(on_send), false) + Basic_client::Basic_client(TCP& tcp, Request_handler on_send) + : Basic_client(tcp, std::move(on_send), false) { } - Client::Client(TCP& tcp, Request_handler on_send, const bool https_supported) + Basic_client::Basic_client(TCP& tcp, Request_handler on_send, const bool https_supported) : tcp_(tcp), on_send_{std::move(on_send)}, supports_https(https_supported) { } - Request_ptr Client::create_request(Method method) const + Request_ptr Basic_client::create_request(Method method) const { auto req = std::make_unique(); req->set_method(method); @@ -45,7 +45,7 @@ namespace http { return req; } - void Client::send(Request_ptr req, Host host, Response_handler cb, + void Basic_client::send(Request_ptr req, Host host, Response_handler cb, const bool secure, Options options) { Expects(cb != nullptr); @@ -63,7 +63,7 @@ namespace http { if(! header.has_field(header::Origin)) header.set_field(header::Origin, origin()); - debug(" Sending Request:\n%s\n", req->to_string().c_str()); + debug(" Sending Request:\n%s\n", req->to_string().c_str()); if(on_send_) on_send_(*req, options, host); @@ -71,7 +71,7 @@ namespace http { conn.send(move(req), move(cb), options.bufsize, options.timeout); } - void Client::request(Method method, URI url, Header_set hfields, + void Basic_client::request(Method method, URI url, Header_set hfields, Response_handler cb, Options options) { Expects(cb != nullptr); @@ -136,7 +136,7 @@ namespace http { } } - void Client::request(Method method, Host host, std::string path, + void Basic_client::request(Method method, Host host, std::string path, Header_set hfields, Response_handler cb, const bool secure, Options options) { @@ -153,7 +153,7 @@ namespace http { send(move(req), move(host), move(cb), secure, move(options)); } - void Client::request(Method method, URI url, Header_set hfields, + void Basic_client::request(Method method, URI url, Header_set hfields, std::string data, Response_handler cb, Options options) { @@ -224,7 +224,7 @@ namespace http { } } - void Client::request(Method method, Host host, std::string path, + void Basic_client::request(Method method, Host host, std::string path, Header_set hfields, const std::string& data, Response_handler cb, const bool secure, Options options) { @@ -244,7 +244,7 @@ namespace http { send(move(req), move(host), move(cb), secure, move(options)); } - void Client::add_data(Request& req, const std::string& data) + void Basic_client::add_data(Request& req, const std::string& data) { auto& header = req.header(); if(!header.has_field(header::Content_Type)) @@ -257,7 +257,7 @@ namespace http { req.add_body(data); } - void Client::populate_from_url(Request& req, const URI& url) + void Basic_client::populate_from_url(Request& req, const URI& url) { // Set uri path (default "/") req.set_uri((!url.path().empty()) ? URI{url.path()} : URI{"/"}); @@ -270,13 +270,13 @@ namespace http { : std::string(url.host())); // to_string madness } - void Client::resolve(const std::string& host, ResolveCallback cb) + void Basic_client::resolve(const std::string& host, ResolveCallback cb) { static auto&& stack = tcp_.stack(); stack.resolve(host, cb); } - Client_connection& Client::get_connection(const Host host) + Client_connection& Basic_client::get_connection(const Host host) { // return/create a set for the given host auto& cset = conns_[host]; @@ -295,14 +295,14 @@ namespace http { return *cset.back(); } - Client_connection& Client::get_secure_connection(const Host) + Client_connection& Basic_client::get_secure_connection(const Host) { throw Client_error{"Secured connections not supported (use the HTTPS Client)."}; } - void Client::close(Client_connection& c) + void Basic_client::close(Client_connection& c) { - debug(" Closing %u:%s %p\n", c.local_port(), c.peer().to_string().c_str(), &c); + debug(" Closing %u:%s %p\n", c.local_port(), c.peer().to_string().c_str(), &c); auto& cset = conns_.at(c.peer()); cset.erase(std::remove_if(cset.begin(), cset.end(), diff --git a/src/net/http/client_connection.cpp b/src/net/http/client_connection.cpp index 1e0e9bf9cd..eb2773239f 100644 --- a/src/net/http/client_connection.cpp +++ b/src/net/http/client_connection.cpp @@ -16,11 +16,11 @@ // limitations under the License. #include -#include +#include namespace http { - Client_connection::Client_connection(Client& client, Stream_ptr stream) + Client_connection::Client_connection(Basic_client& client, Stream_ptr stream) : Connection{std::move(stream)}, client_(client), req_(nullptr), diff --git a/src/net/ws/websocket.cpp b/src/net/ws/websocket.cpp index bb965365dc..6892a325d5 100644 --- a/src/net/ws/websocket.cpp +++ b/src/net/ws/websocket.cpp @@ -148,10 +148,10 @@ http::Server::Request_handler WebSocket::create_request_handler( }); } -http::Client::Response_handler WebSocket::create_response_handler( +http::Basic_client::Response_handler WebSocket::create_response_handler( Connect_handler on_connect, std::string key) { - return http::Client::Response_handler::make_packed( + return http::Basic_client::Response_handler::make_packed( [ on_connect{std::move(on_connect)}, key{std::move(key)} @@ -165,9 +165,9 @@ http::Client::Response_handler WebSocket::create_response_handler( } void WebSocket::connect( - http::Client& client, - uri::URI remote, - Connect_handler callback) + http::Basic_client& client, + uri::URI remote, + Connect_handler callback) { // doesn't have to be extremely random, just random std::string key = base64::encode(generate_key()); diff --git a/test/net/integration/http/service.cpp b/test/net/integration/http/service.cpp index 370dd16254..e54a10f65e 100644 --- a/test/net/integration/http/service.cpp +++ b/test/net/integration/http/service.cpp @@ -16,13 +16,13 @@ // limitations under the License. #include -#include +#include #include #include #include #include -std::unique_ptr client_; +std::unique_ptr client_; std::unique_ptr server_; void Service::start(const std::string&) @@ -58,13 +58,13 @@ void Service::ready() server_->listen(8080); - client_ = std::make_unique(inet.tcp()); - client_->on_send([] (Request& req, Client::Options& opt, const Client::Host host) + client_ = std::make_unique(inet.tcp()); + client_->on_send([] (Request& req, Basic_client::Options& opt, const Basic_client::Host host) { printf("Sending request:\n%s\n", req.to_string().c_str()); }); - INFO("Client", "Testing against local server"); + INFO("Basic_client", "Testing against local server"); auto req = client_->create_request(); @@ -84,7 +84,7 @@ void Service::ready() }); - INFO("Client", "Testing against Acorn"); + INFO("Basic_client", "Testing against Acorn"); const std::string acorn_url{"http://acorn2.unofficial.includeos.io/"}; @@ -108,16 +108,16 @@ void Service::ready() }, { 3s }); - INFO("Client", "HTTPS"); + INFO("Basic_client", "HTTPS"); try { client_->get("https://www.google.com", {}, [](Error err, Response_ptr res, Connection&) {}); - assert(false && "Client should throw exception"); + assert(false && "Basic Client should throw exception"); } catch(const http::Client_error& err) { - CHECKSERT(true, "HTTP Client should throw exception on https URL"); + CHECKSERT(true, "Basic Client should throw exception on https URL"); } } From 5ec7a52659f452c5b7d8a7957b2707de6a420060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Tue, 27 Mar 2018 11:49:31 +0200 Subject: [PATCH 14/23] http: Added https supported Client inherting Basic_client --- api/net/http/client.hpp | 39 ++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 3 ++- src/net/http/client.cpp | 49 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 api/net/http/client.hpp create mode 100644 src/net/http/client.cpp diff --git a/api/net/http/client.hpp b/api/net/http/client.hpp new file mode 100644 index 0000000000..03de404e17 --- /dev/null +++ b/api/net/http/client.hpp @@ -0,0 +1,39 @@ +// This file is a part of the IncludeOS unikernel - www.includeos.org +// +// Copyright 2018 IncludeOS AS, Oslo, Norway +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#ifndef NET_HTTP_CLIENT_HPP +#define NET_HTTP_CLIENT_HPP + +#include +#include + +namespace http { + + class Client : public http::Basic_client { + public: + explicit Client(TCP& tcp, SSL_CTX* ssl_ctx, Request_handler on_send = nullptr); + + private: + SSL_CTX* ssl_context; + + virtual Client_connection& get_secure_connection(const Host host) override; + + }; // < class Client + +} // < namespace http + +#endif // < NET_HTTP_CLIENT_HPP diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5f633b3a51..2b0270a236 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,7 +21,8 @@ include_directories(${BOTAN_DIR}) include_directories(${OPENSSL_DIR}) include_directories(${OPENSSL_DIR}/include) if(${ARCH} STREQUAL "x86_64") - set(OPENSSL_MODULES "net/openssl/init.cpp" "net/openssl/client.cpp" "net/https/openssl_server.cpp") + set(OPENSSL_MODULES "net/openssl/init.cpp" "net/openssl/client.cpp" "net/https/openssl_server.cpp" + "net/http/client.cpp") set(OPENSSL_LIBS openssl_ssl openssl_crypto) endif() set(BOTAN_MODULES "net/https/botan_server.cpp") diff --git a/src/net/http/client.cpp b/src/net/http/client.cpp new file mode 100644 index 0000000000..1ee5278b1e --- /dev/null +++ b/src/net/http/client.cpp @@ -0,0 +1,49 @@ +// This file is a part of the IncludeOS unikernel - www.includeos.org +// +// Copyright 2018 IncludeOS AS, Oslo, Norway +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include + +namespace http { + + Client::Client(TCP& tcp, SSL_CTX* ssl_ctx, Request_handler on_send) + : http::Basic_client(tcp, std::move(on_send), true), + ssl_context(ssl_ctx) + { + } + + Client_connection& Client::get_secure_connection(const Host host) + { + // return/create a set for the given host + auto& cset = conns_[host]; + + // iterate all the connection and return the first free one + for(auto& conn : cset) + { + if(!conn->occupied()) + return *conn; + } + + auto tcp_stream = std::make_unique(tcp_.connect(host)); + auto tls_stream = std::make_unique(ssl_context, std::move(tcp_stream), true); + + cset.push_back(std::make_unique(*this, std::move(tls_stream))); + + return *cset.back(); + } + +} From faeb86dcbee80689d2fc14b9391b3456edf5ebf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Tue, 27 Mar 2018 12:05:10 +0200 Subject: [PATCH 15/23] examples: Added HTTP Client example, removed TLS_client example --- examples/TLS_client/README.md | 13 ---- examples/TLS_client/config.json | 11 --- examples/TLS_client/http.cpp | 55 ------------- examples/TLS_client/service.cpp | 78 ------------------- .../CMakeLists.txt | 20 +++-- examples/http_client/README.md | 11 +++ .../certs}/server.pem | 0 examples/http_client/nacl.txt | 7 ++ examples/http_client/service.cpp | 78 +++++++++++++++++++ examples/http_client/vm.json | 5 ++ 10 files changed, 110 insertions(+), 168 deletions(-) delete mode 100644 examples/TLS_client/README.md delete mode 100644 examples/TLS_client/config.json delete mode 100644 examples/TLS_client/http.cpp delete mode 100644 examples/TLS_client/service.cpp rename examples/{TLS_client => http_client}/CMakeLists.txt (59%) create mode 100644 examples/http_client/README.md rename examples/{TLS_client => http_client/certs}/server.pem (100%) create mode 100644 examples/http_client/nacl.txt create mode 100644 examples/http_client/service.cpp create mode 100644 examples/http_client/vm.json diff --git a/examples/TLS_client/README.md b/examples/TLS_client/README.md deleted file mode 100644 index 3ab5920c95..0000000000 --- a/examples/TLS_client/README.md +++ /dev/null @@ -1,13 +0,0 @@ -### TLS client demo service - -To start, using boot: -``` -boot . -``` - -This demo-service should should connect with TLS 1.2 to 10.0.0.1:2345. - -To test (from service folder): -``` -openssl s_server -port 2345 -``` diff --git a/examples/TLS_client/config.json b/examples/TLS_client/config.json deleted file mode 100644 index 26564e1325..0000000000 --- a/examples/TLS_client/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "net" : [ - { - "iface": 0, - "config": "static", - "address": "10.0.0.42", - "netmask": "255.255.255.0", - "gateway": "10.0.0.1" - } - ] -} diff --git a/examples/TLS_client/http.cpp b/examples/TLS_client/http.cpp deleted file mode 100644 index a09ca46c81..0000000000 --- a/examples/TLS_client/http.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include // rand() -#include -#include -#include - -using namespace std::chrono; - -std::string HTML_RESPONSE() -{ - const int color = rand(); - - // Generate some HTML - std::stringstream stream; - stream << "" - << "" - << "IncludeOS Demo Service" - << "

" - << "IncludeOS

" - << "

The C++ Unikernel

" - << "

You have successfully booted an IncludeOS TCP service with simple https. " - << "For a more sophisticated example, take a look at " - << "Acorn.

" - << "

© 2017 IncludeOS
"; - - return stream.str(); -} - -http::Response_ptr handle_request(const http::Request& req) -{ - auto res = http::make_response(); - auto& header = res->header(); - - header.set_field(http::header::Server, "IncludeOS/0.12"); - - // GET / - if(req.method() == http::GET && req.uri().to_string() == "/") - { - // add HTML response - res->add_body(HTML_RESPONSE()); - - // set Content type and length - header.set_field(http::header::Content_Type, "text/html; charset=UTF-8"); - header.set_field(http::header::Content_Length, std::to_string(res->body().size())); - } - else - { - // Generate 404 response - res->set_status_code(http::Not_Found); - } - - header.set_field(http::header::Connection, "close"); - return res; -} diff --git a/examples/TLS_client/service.cpp b/examples/TLS_client/service.cpp deleted file mode 100644 index b8891a2193..0000000000 --- a/examples/TLS_client/service.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// This file is a part of the IncludeOS unikernel - www.includeos.org -// -// Copyright 2015 Oslo and Akershus University College of Applied Sciences -// and Alfred Bratterud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include -#include - -namespace acorn { - extern void list_static_content(const fs::File_system&); -} - -void Service::start() -{ - // Get the first IP stack - // It should have configuration from config.json - auto& inet = net::Super_stack::get(0); - - fs::memdisk().init_fs( - [] (auto err, auto& fs) { - assert(!err); - //acorn::list_static_content(fs); - (void) fs; - }); - - // initialize client context - openssl::init(); - auto* ctx = openssl::create_client("/ca/"); - - printf("Connecting to https://www.google.com..."); - inet.tcp().connect( - {{"173.194.221.105"}, 443}, - [ctx] (auto conn) { - if (conn == nullptr) { - printf("Could not connect...\n"); - return; - } - printf("Connected to %s\n", conn->remote().to_string().c_str()); - auto tcp_stream = std::make_unique(std::move(conn)); - - auto* stream = new openssl::TLS_stream(ctx, std::move(tcp_stream), true); - stream->on_connect( - [] (auto& stream) - { - stream.write("GET /\r\n\r\n"); - - stream.on_read(8192, - [strim = &stream] (auto buf) { - printf("on_read(%lu): %.*s\n", - buf->size(), - (int) buf->size(), buf->data()); - strim->write(buf); - }); - }); - stream->on_close( - [stream] { - printf("Stream closed\n"); - delete stream; - }); - }); - -} diff --git a/examples/TLS_client/CMakeLists.txt b/examples/http_client/CMakeLists.txt similarity index 59% rename from examples/TLS_client/CMakeLists.txt rename to examples/http_client/CMakeLists.txt index 332d6c707f..e3b9233a8f 100644 --- a/examples/TLS_client/CMakeLists.txt +++ b/examples/http_client/CMakeLists.txt @@ -5,28 +5,26 @@ if (NOT DEFINED ENV{INCLUDEOS_PREFIX}) set(ENV{INCLUDEOS_PREFIX} /usr/local) endif() include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake) -project (demo_service) +project (http_client) # Human-readable name of your service -set(SERVICE_NAME "IncludeOS TLS example") +set(SERVICE_NAME "IncludeOS HTTP Client example") + # Name of your service binary -set(BINARY "tls_client") +set(BINARY "http_client") # Source files to be linked with OS library parts to form bootable image set(SOURCES service.cpp - http.cpp - ../acorn/fs/acorn_fs.cpp ) -# DRIVERS / PLUGINS: set(DRIVERS - virtionet # Virtio networking - # virtioblock # Virtio block device - # ... Others from src/drivers + virtionet + vmxnet3 + e1000 + boot_logger ) -# include service build script include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake) -diskbuilder(disk) +diskbuilder(certs) diff --git a/examples/http_client/README.md b/examples/http_client/README.md new file mode 100644 index 0000000000..d52777ac90 --- /dev/null +++ b/examples/http_client/README.md @@ -0,0 +1,11 @@ +### IncludeOS HTTP Client example + +To start, using boot: +``` +boot . +``` + +This example will send a GET request to http://www.google.com with our Basic_client, and to https://www.google.com with our HTTPS supported Client. +For the example to succeed, make sure your virtual machine can reach the internet (ip forward & nat). + +For example purpose only. Don't reuse the `server.pem` certificate. diff --git a/examples/TLS_client/server.pem b/examples/http_client/certs/server.pem similarity index 100% rename from examples/TLS_client/server.pem rename to examples/http_client/certs/server.pem diff --git a/examples/http_client/nacl.txt b/examples/http_client/nacl.txt new file mode 100644 index 0000000000..75f41f7e04 --- /dev/null +++ b/examples/http_client/nacl.txt @@ -0,0 +1,7 @@ +Iface eth0 { + index: 0, + address: 10.0.0.42, + netmask: 255.255.255.0, + gateway: 10.0.0.1, + dns: 8.8.8.8 +} diff --git a/examples/http_client/service.cpp b/examples/http_client/service.cpp new file mode 100644 index 0000000000..315777e70f --- /dev/null +++ b/examples/http_client/service.cpp @@ -0,0 +1,78 @@ +// This file is a part of the IncludeOS unikernel - www.includeos.org +// +// Copyright 2016 Oslo and Akershus University College of Applied Sciences +// and Alfred Bratterud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +static SSL_CTX* init_ssl_context() +{ + fs::memdisk().init_fs( + [] (auto err, auto&) { + assert(!err); + }); + + // initialize client context + openssl::init(); + return openssl::create_client("/"); +} + +#include +#include +#include +#include + +void Service::start() +{ + auto& inet = net::Super_stack::get(0); + + using namespace http; + + static Basic_client basic{inet.tcp()}; + + const std::string url{"http://www.google.com"}; + INFO("HTTP", "GET %s", url.c_str()); + + basic.get(url, {}, [url](Error err, Response_ptr res, Connection&) + { + if(not err) { + printf("\n%s - Got Response!\n%s\n", url.c_str(), res->to_string().c_str()); + } + else { + printf("\n%s - No response: %s\n", url.c_str(), err.to_string().c_str()); + printf("Make sure the virtual machine can reach internet.\n"); + } + }); + + auto* ctx = init_ssl_context(); + assert(ctx != nullptr); + + static Client client{inet.tcp(), ctx}; + + const std::string url_sec{"https://www.google.com"}; + INFO("HTTPS", "(Secure) GET %s", url_sec.c_str()); + + client.get("https://www.google.com", {}, [url = url_sec](Error err, Response_ptr res, Connection&) + { + if(not err) { + printf("\n%s - Got Response!\n%s\n", url.c_str(), res->to_string().c_str()); + } + else { + printf("\n%s - No response: %s\n", url.c_str(), err.to_string().c_str()); + printf("Make sure the virtual machine can reach internet.\n"); + } + }); +} diff --git a/examples/http_client/vm.json b/examples/http_client/vm.json new file mode 100644 index 0000000000..d0dae980d0 --- /dev/null +++ b/examples/http_client/vm.json @@ -0,0 +1,5 @@ +{ + "net" : [ + {"device" : "virtio", "mac" : "c0:01:0a:00:00:2a"} + ] +} From c68814165ac43b8911a06edb578ea9cefceaeedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Tue, 27 Mar 2018 12:05:45 +0200 Subject: [PATCH 16/23] openssl: Print version info on init --- src/net/openssl/init.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net/openssl/init.cpp b/src/net/openssl/init.cpp index 3326b2df4a..f6297b93a3 100644 --- a/src/net/openssl/init.cpp +++ b/src/net/openssl/init.cpp @@ -7,6 +7,7 @@ #include #include #include +#include extern "C" void ios_rand_seed(const void* buf, int num) { @@ -63,6 +64,7 @@ namespace openssl static bool init_once = false; if (init_once == false) { + INFO("OpenSSL", "Initializing (%s)", OPENSSL_VERSION_TEXT); init_once = true; SSL_library_init(); OpenSSL_add_all_algorithms(); From 6738d694f73683f1359ac308931401a256275197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Tue, 27 Mar 2018 13:14:28 +0200 Subject: [PATCH 17/23] openssl: Now takes dirent list as arg for certificates --- api/net/openssl/init.hpp | 3 ++- examples/http_client/service.cpp | 8 +++++--- src/net/openssl/client.cpp | 20 ++++++++------------ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/api/net/openssl/init.hpp b/api/net/openssl/init.hpp index f08eb058ad..71547d0cf2 100644 --- a/api/net/openssl/init.hpp +++ b/api/net/openssl/init.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include namespace openssl { @@ -7,7 +8,7 @@ namespace openssl extern void verify_rng(); extern void init(); - extern SSL_CTX* create_client(const char* path, bool verify_peer = false); + extern SSL_CTX* create_client(fs::List, bool verify_peer = false); // enable peer certificate verification extern void client_verify_peer(SSL_CTX*); } diff --git a/examples/http_client/service.cpp b/examples/http_client/service.cpp index 315777e70f..647e593a9f 100644 --- a/examples/http_client/service.cpp +++ b/examples/http_client/service.cpp @@ -20,14 +20,16 @@ static SSL_CTX* init_ssl_context() { - fs::memdisk().init_fs( - [] (auto err, auto&) { + auto& disk = fs::memdisk(); + disk.init_fs([] (auto err, auto&) { assert(!err); }); + auto ents = disk.fs().ls("/"); + // initialize client context openssl::init(); - return openssl::create_client("/"); + return openssl::create_client(ents); } #include diff --git a/src/net/openssl/client.cpp b/src/net/openssl/client.cpp index 189c4adf96..1592d0d976 100644 --- a/src/net/openssl/client.cpp +++ b/src/net/openssl/client.cpp @@ -1,8 +1,8 @@ #include #include #include -#include -#define LOAD_FROM_MEMDISK +#include +#include // https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca inline void handle_error(const char* file, int lineno, const char* msg) { @@ -48,7 +48,7 @@ tls_private_key_for_ctx(SSL_CTX* ctx, int bits = 2048) } static SSL_CTX* -tls_init_client(const char* path) +tls_init_client(fs::List ents) { /* create the SSL server context */ auto meth = TLSv1_2_method(); @@ -61,21 +61,15 @@ tls_init_client(const char* path) X509_STORE* store = X509_STORE_new(); assert(store != nullptr); -#ifdef LOAD_FROM_MEMDISK - auto& filesys = fs::memdisk().fs(); - auto ents = filesys.ls(path); for (auto& ent : ents) { if (ent.is_file()) { - printf("Loading cert %s\n", ent.name().c_str()); + INFO2("Loading certificate %s", ent.name().c_str()); auto buffer = ent.read(0, ent.size()); tls_load_from_memory(store, buffer); } } -#else -# error "Implement me" -#endif // assign CA store to CTX SSL_CTX_set_cert_store(ctx, store); @@ -92,9 +86,11 @@ tls_init_client(const char* path) namespace openssl { - SSL_CTX* create_client(const char* path, bool verify_peer) + SSL_CTX* create_client(fs::List ents, bool verify_peer) { - auto* ctx = tls_init_client(path); + INFO("OpenSSL", "Initializing client context"); + auto* ctx = tls_init_client(ents); + CHECK(verify_peer, "Verify peer"); if (verify_peer) client_verify_peer(ctx); return ctx; } From 52e8f82235f44a897ca8e5bc3a7298245982701e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Tue, 3 Apr 2018 09:49:34 +0200 Subject: [PATCH 18/23] test: Don't compile http client in unittest --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a02bd435ef..dc117ec28f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -167,7 +167,7 @@ set(OS_SOURCES ${SRC}/net/dns/client.cpp ${SRC}/net/dns/dns.cpp ${SRC}/net/ethernet/ethernet.cpp - ${SRC}/net/http/client.cpp + ${SRC}/net/http/basic_client.cpp ${SRC}/net/http/client_connection.cpp ${SRC}/net/http/cookie.cpp ${SRC}/net/http/header.cpp From 1ee3c06fb10ea5e266dd7084e761cda47fce3b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85kesson?= Date: Tue, 3 Apr 2018 10:13:09 +0200 Subject: [PATCH 19/23] test: Websocket test use basic http client --- test/net/integration/websocket/service.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/net/integration/websocket/service.cpp b/test/net/integration/websocket/service.cpp index 70d355554d..4a462c81ec 100644 --- a/test/net/integration/websocket/service.cpp +++ b/test/net/integration/websocket/service.cpp @@ -98,7 +98,7 @@ void Service::start() void ws_client_test(net::TCP& tcp) { /// client /// - static http::Client client(tcp); + static http::Basic_client client(tcp); net::WebSocket::connect(client, "ws://10.0.0.1:8001/", [] (net::WebSocket_ptr socket) { From 7c82c06e323734d075033800b13ae9f0ab0e2546 Mon Sep 17 00:00:00 2001 From: niks3089 Date: Thu, 5 Apr 2018 03:05:17 -0700 Subject: [PATCH 20/23] Pass kernel arguments so that when solo5 is booted, it can parse it as command line --- vmrunner/vmrunner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/vmrunner/vmrunner.py b/vmrunner/vmrunner.py index bc30fcbd1e..5aed05453d 100644 --- a/vmrunner/vmrunner.py +++ b/vmrunner/vmrunner.py @@ -239,6 +239,7 @@ def boot(self, multiboot, debug=False, kernel_args = "", image_name = None): command += self.drive_arg() command += self.net_arg() command += [self._image_name] + command += [kernel_args] try: self.start_process(command) From 0f2c263aa9370807df3e33287d4a5019e50007e6 Mon Sep 17 00:00:00 2001 From: Ingve Vormestrand Date: Thu, 5 Apr 2018 13:10:25 +0200 Subject: [PATCH 21/23] x86: use fallback with CMOS for Clocks::init --- src/platform/x86_pc/clocks.cpp | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/platform/x86_pc/clocks.cpp b/src/platform/x86_pc/clocks.cpp index c47429c2cf..cc137eb70e 100644 --- a/src/platform/x86_pc/clocks.cpp +++ b/src/platform/x86_pc/clocks.cpp @@ -43,24 +43,13 @@ namespace x86 void Clocks::init() { - if (CPUID::kvm_feature(KVM_FEATURE_CLOCKSOURCE2)) - { - KVM_clock::init(); - PER_CPU(vcpu_clock).system_time = {&KVM_clock::system_time}; - PER_CPU(vcpu_clock).wall_time = {&KVM_clock::wall_clock}; - PER_CPU(vcpu_clock).tsc_khz = {&KVM_clock::get_tsc_khz}; - if (SMP::cpu_id() == 0) INFO("x86", "KVM PV clocks initialized"); - } - else - { - // fallback with CMOS - PER_CPU(vcpu_clock).system_time = {&CMOS_clock::system_time}; - PER_CPU(vcpu_clock).wall_time = {&CMOS_clock::wall_clock}; - PER_CPU(vcpu_clock).tsc_khz = {&CMOS_clock::get_tsc_khz}; - if (SMP::cpu_id() == 0) { - CMOS_clock::init(); - INFO("x86", "CMOS clock initialized"); - } + // fallback with CMOS + PER_CPU(vcpu_clock).system_time = {&CMOS_clock::system_time}; + PER_CPU(vcpu_clock).wall_time = {&CMOS_clock::wall_clock}; + PER_CPU(vcpu_clock).tsc_khz = {&CMOS_clock::get_tsc_khz}; + if (SMP::cpu_id() == 0) { + CMOS_clock::init(); + INFO("x86", "CMOS clock initialized"); } } From 3b87f22b2f9e52dc67e68f7ac43ca5bb04f5db5f Mon Sep 17 00:00:00 2001 From: Ingve Vormestrand Date: Thu, 5 Apr 2018 16:16:09 +0200 Subject: [PATCH 22/23] x86: use fallback with CMOS for Clocks::init, keep KVM clock part --- src/platform/x86_pc/clocks.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/platform/x86_pc/clocks.cpp b/src/platform/x86_pc/clocks.cpp index cc137eb70e..68b911e280 100644 --- a/src/platform/x86_pc/clocks.cpp +++ b/src/platform/x86_pc/clocks.cpp @@ -43,13 +43,24 @@ namespace x86 void Clocks::init() { - // fallback with CMOS - PER_CPU(vcpu_clock).system_time = {&CMOS_clock::system_time}; - PER_CPU(vcpu_clock).wall_time = {&CMOS_clock::wall_clock}; - PER_CPU(vcpu_clock).tsc_khz = {&CMOS_clock::get_tsc_khz}; - if (SMP::cpu_id() == 0) { - CMOS_clock::init(); - INFO("x86", "CMOS clock initialized"); + if (false && CPUID::kvm_feature(KVM_FEATURE_CLOCKSOURCE2)) + { + KVM_clock::init(); + PER_CPU(vcpu_clock).system_time = {&KVM_clock::system_time}; + PER_CPU(vcpu_clock).wall_time = {&KVM_clock::wall_clock}; + PER_CPU(vcpu_clock).tsc_khz = {&KVM_clock::get_tsc_khz}; + if (SMP::cpu_id() == 0) INFO("x86", "KVM PV clocks initialized"); + } + else + { + // fallback with CMOS + PER_CPU(vcpu_clock).system_time = {&CMOS_clock::system_time}; + PER_CPU(vcpu_clock).wall_time = {&CMOS_clock::wall_clock}; + PER_CPU(vcpu_clock).tsc_khz = {&CMOS_clock::get_tsc_khz}; + if (SMP::cpu_id() == 0) { + CMOS_clock::init(); + INFO("x86", "CMOS clock initialized"); + } } } From 35ccc66d33b4ec9499d166f37cc10f5f7447e86d Mon Sep 17 00:00:00 2001 From: Ingve Vormestrand Date: Fri, 6 Apr 2018 16:21:47 +0200 Subject: [PATCH 23/23] uplink: removed unused variable --- lib/uplink/ws_uplink.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/uplink/ws_uplink.hpp b/lib/uplink/ws_uplink.hpp index b6369d6bac..2f1518290f 100644 --- a/lib/uplink/ws_uplink.hpp +++ b/lib/uplink/ws_uplink.hpp @@ -74,7 +74,6 @@ class WS_uplink { net::WebSocket_ptr ws_; std::string id_; std::string token_; - std::string tag_; /** Hash for the current running binary * (restored during update, none if never updated) */ std::string binary_hash_;