From 8ffc17a3ba50bf245737a571ae055539ec13252f Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 26 Mar 2024 16:15:31 +0800 Subject: [PATCH 1/6] support set address --- include/cinatra/coro_http_server.hpp | 63 +++++++++++++++++++++------- tests/test_cinatra.cpp | 31 ++++++++++++++ 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/include/cinatra/coro_http_server.hpp b/include/cinatra/coro_http_server.hpp index 86b08ed2..68006ada 100644 --- a/include/cinatra/coro_http_server.hpp +++ b/include/cinatra/coro_http_server.hpp @@ -27,16 +27,21 @@ enum class file_resp_format_type { }; class coro_http_server { public: - coro_http_server(asio::io_context &ctx, unsigned short port) - : out_ctx_(&ctx), port_(port), acceptor_(ctx), check_timer_(ctx) {} + coro_http_server(asio::io_context &ctx, unsigned short port, + std::string address = "0.0.0.0") + : out_ctx_(&ctx), port_(port), acceptor_(ctx), check_timer_(ctx) { + init_address(address); + } coro_http_server(size_t thread_num, unsigned short port, - bool cpu_affinity = false) + std::string address = "0.0.0.0", bool cpu_affinity = false) : pool_(std::make_unique(thread_num, cpu_affinity)), port_(port), acceptor_(pool_->get_executor()->get_asio_executor()), - check_timer_(pool_->get_executor()->get_asio_executor()) {} + check_timer_(pool_->get_executor()->get_asio_executor()) { + init_address(address); + } ~coro_http_server() { CINATRA_LOG_INFO << "coro_http_server will quit"; @@ -64,21 +69,22 @@ class coro_http_server { // only call once, not thread safe. async_simple::Future async_start() { - auto ec = listen(); + errc_ = listen(); async_simple::Promise promise; auto future = promise.getFuture(); - if (ec == std::errc{}) { + if (errc_ == std::errc{}) { if (out_ctx_ == nullptr) { thd_ = std::thread([this] { pool_->run(); }); } - accept().start([p = std::move(promise)](auto &&res) mutable { + accept().start([p = std::move(promise), this](auto &&res) mutable { if (res.hasError()) { - p.setValue(std::errc::io_error); + errc_ = std::errc::io_error; + p.setValue(errc_); } else { p.setValue(res.value()); @@ -86,7 +92,7 @@ class coro_http_server { }); } else { - promise.setValue(ec); + promise.setValue(errc_); } return future; @@ -488,16 +494,31 @@ class coro_http_server { return connections_.size(); } + std::string_view address() { return address_; } + std::errc get_errc() { return errc_; } + private: std::errc listen() { CINATRA_LOG_INFO << "begin to listen"; using asio::ip::tcp; - auto endpoint = tcp::endpoint(tcp::v4(), port_); - acceptor_.open(endpoint.protocol()); + asio::error_code ec; + auto addr = asio::ip::address::from_string(address_, ec); + if (ec) { + CINATRA_LOG_ERROR << "bad address: " << address_ + << " error: " << ec.message(); + return std::errc::bad_address; + } + + auto endpoint = tcp::endpoint(addr, port_); + acceptor_.open(endpoint.protocol(), ec); + if (ec) { + CINATRA_LOG_ERROR << "acceptor open failed" + << " error: " << ec.message(); + return std::errc::io_error; + } #ifdef __GNUC__ - acceptor_.set_option(tcp::acceptor::reuse_address(true)); + acceptor_.set_option(tcp::acceptor::reuse_address(true), ec); #endif - asio::error_code ec; acceptor_.bind(endpoint, ec); if (ec) { CINATRA_LOG_ERROR << "bind port: " << port_ << " error: " << ec.message(); @@ -508,7 +529,12 @@ class coro_http_server { #ifdef _MSC_VER acceptor_.set_option(tcp::acceptor::reuse_address(true)); #endif - acceptor_.listen(); + acceptor_.listen(asio::socket_base::max_listen_connections, ec); + if (ec) { + CINATRA_LOG_ERROR << "get local endpoint port: " << port_ + << " listen error: " << ec.message(); + return std::errc::io_error; + } auto end_point = acceptor_.local_endpoint(ec); if (ec) { @@ -749,11 +775,20 @@ class coro_http_server { response.set_delay(true); } + void init_address(std::string &address) { + if (iequal0(address, "localhost")) { + address = "127.0.0.1"; + } + address_ = std::move(address); + } + private: std::unique_ptr pool_; asio::io_context *out_ctx_ = nullptr; std::unique_ptr> out_executor_ = nullptr; uint16_t port_; + std::string address_; + std::errc errc_ = {}; asio::ip::tcp::acceptor acceptor_; std::thread thd_; std::promise acceptor_close_waiter_; diff --git a/tests/test_cinatra.cpp b/tests/test_cinatra.cpp index a5689685..bb433c6a 100644 --- a/tests/test_cinatra.cpp +++ b/tests/test_cinatra.cpp @@ -317,6 +317,37 @@ TEST_CASE("test select coro channel") { CHECK(val == 42); } +TEST_CASE("test bad address") { + { + coro_http_server server(1, 9001, "127.0.0.1"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc{}); + } + { + coro_http_server server(1, 9001, "localhost"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc{}); + } + { + coro_http_server server(1, 9001, "0.0.0.0"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc{}); + } + { + coro_http_server server(1, 9001); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc{}); + } + coro_http_server server(1, 9001, "x.x.x"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc::bad_address); +} + async_simple::coro::Lazy test_collect_all() { asio::io_context ioc; std::thread thd([&] { From b7caa092acde3aba3ca15a1137c219259d8f3357 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 26 Mar 2024 16:16:56 +0800 Subject: [PATCH 2/6] revert cmake setting --- cmake/develop.cmake | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cmake/develop.cmake b/cmake/develop.cmake index e9ec2529..864fb2b5 100644 --- a/cmake/develop.cmake +++ b/cmake/develop.cmake @@ -39,11 +39,7 @@ int main() endmacro() # Enable address sanitizer -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - option(ENABLE_SANITIZER "Enable sanitizer(Debug+Gcc/Clang/AppleClang)" OFF) -else() - option(ENABLE_SANITIZER "Enable sanitizer(Debug+Gcc/Clang/AppleClang)" ON) -endif() +option(ENABLE_SANITIZER "Enable sanitizer(Debug+Gcc/Clang/AppleClang)" ON) if(ENABLE_SANITIZER AND NOT MSVC) if(CMAKE_BUILD_TYPE STREQUAL "Debug") check_asan(HAS_ASAN) From 3db2b6065bee9ca93c3fa1be9bdbaf68c46cedd4 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 26 Mar 2024 16:24:39 +0800 Subject: [PATCH 3/6] fix compile --- example/benchmark.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/benchmark.cpp b/example/benchmark.cpp index 45d55f53..ef0c6640 100644 --- a/example/benchmark.cpp +++ b/example/benchmark.cpp @@ -4,7 +4,8 @@ using namespace cinatra; using namespace std::chrono_literals; int main() { - coro_http_server server(std::thread::hardware_concurrency(), 8090, true); + coro_http_server server(std::thread::hardware_concurrency(), 8090, + "127.0.0.1", true); server.set_http_handler( "/plaintext", [](coro_http_request& req, coro_http_response& resp) { resp.get_conn()->set_multi_buf(false); From d5033e820e627fd15948b520ba74addde6458311 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Wed, 27 Mar 2024 10:17:25 +0800 Subject: [PATCH 4/6] host:port --- include/cinatra/coro_http_server.hpp | 29 +++++++++++++++++++++++++--- tests/test_cinatra.cpp | 18 +++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/cinatra/coro_http_server.hpp b/include/cinatra/coro_http_server.hpp index 68006ada..bbe27734 100644 --- a/include/cinatra/coro_http_server.hpp +++ b/include/cinatra/coro_http_server.hpp @@ -30,7 +30,13 @@ class coro_http_server { coro_http_server(asio::io_context &ctx, unsigned short port, std::string address = "0.0.0.0") : out_ctx_(&ctx), port_(port), acceptor_(ctx), check_timer_(ctx) { - init_address(address); + init_address(std::move(address)); + } + + coro_http_server(asio::io_context &ctx, + std::string address /* = "0.0.0.0:9001" */) + : out_ctx_(&ctx), acceptor_(ctx), check_timer_(ctx) { + init_address(std::move(address)); } coro_http_server(size_t thread_num, unsigned short port, @@ -40,7 +46,17 @@ class coro_http_server { port_(port), acceptor_(pool_->get_executor()->get_asio_executor()), check_timer_(pool_->get_executor()->get_asio_executor()) { - init_address(address); + init_address(std::move(address)); + } + + coro_http_server(size_t thread_num, + std::string address /* = "0.0.0.0:9001" */, + bool cpu_affinity = false) + : pool_(std::make_unique(thread_num, + cpu_affinity)), + acceptor_(pool_->get_executor()->get_asio_executor()), + check_timer_(pool_->get_executor()->get_asio_executor()) { + init_address(std::move(address)); } ~coro_http_server() { @@ -775,10 +791,17 @@ class coro_http_server { response.set_delay(true); } - void init_address(std::string &address) { + void init_address(std::string address) { + if (size_t pos = address.find(':'); pos != std::string::npos) { + auto port = std::string_view(address).substr(pos + 1); + port_ = (uint16_t)atoi(port.data()); + address = address.substr(0, pos); + } + if (iequal0(address, "localhost")) { address = "127.0.0.1"; } + address_ = std::move(address); } diff --git a/tests/test_cinatra.cpp b/tests/test_cinatra.cpp index bb433c6a..f83d03be 100644 --- a/tests/test_cinatra.cpp +++ b/tests/test_cinatra.cpp @@ -342,6 +342,24 @@ TEST_CASE("test bad address") { auto ec = server.get_errc(); CHECK(ec == std::errc{}); } + { + coro_http_server server(1, "0.0.0.0:9001"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc{}); + } + { + coro_http_server server(1, "127.0.0.1:9001"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc{}); + } + { + coro_http_server server(1, "localhost:9001"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc{}); + } coro_http_server server(1, 9001, "x.x.x"); server.async_start(); auto ec = server.get_errc(); From bc62641704ddb984f134851670c357dc966a4721 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Wed, 27 Mar 2024 10:42:58 +0800 Subject: [PATCH 5/6] improve --- include/cinatra/coro_http_server.hpp | 13 +++++++++++-- tests/test_cinatra.cpp | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/cinatra/coro_http_server.hpp b/include/cinatra/coro_http_server.hpp index bbe27734..566f1672 100644 --- a/include/cinatra/coro_http_server.hpp +++ b/include/cinatra/coro_http_server.hpp @@ -793,8 +793,17 @@ class coro_http_server { void init_address(std::string address) { if (size_t pos = address.find(':'); pos != std::string::npos) { - auto port = std::string_view(address).substr(pos + 1); - port_ = (uint16_t)atoi(port.data()); + auto port_sv = std::string_view(address).substr(pos + 1); + + uint16_t port; + auto [ptr, ec] = + std::from_chars(port_sv.begin(), port_sv.end(), port, 10); + if (ec != std::errc{}) { + address_ = std::move(address); + return; + } + + port_ = port; address = address.substr(0, pos); } diff --git a/tests/test_cinatra.cpp b/tests/test_cinatra.cpp index f83d03be..8571c696 100644 --- a/tests/test_cinatra.cpp +++ b/tests/test_cinatra.cpp @@ -360,10 +360,19 @@ TEST_CASE("test bad address") { auto ec = server.get_errc(); CHECK(ec == std::errc{}); } - coro_http_server server(1, 9001, "x.x.x"); - server.async_start(); - auto ec = server.get_errc(); - CHECK(ec == std::errc::bad_address); + + { + coro_http_server server(1, 9001, "x.x.x"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc::bad_address); + } + { + coro_http_server server(1, "localhost:aaa"); + server.async_start(); + auto ec = server.get_errc(); + CHECK(ec == std::errc::bad_address); + } } async_simple::coro::Lazy test_collect_all() { From 247cdf4c480451e33bbfcf1233f8da8db99d19a6 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Wed, 27 Mar 2024 10:50:38 +0800 Subject: [PATCH 6/6] for msvc --- include/cinatra/coro_http_server.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cinatra/coro_http_server.hpp b/include/cinatra/coro_http_server.hpp index 566f1672..e9220be4 100644 --- a/include/cinatra/coro_http_server.hpp +++ b/include/cinatra/coro_http_server.hpp @@ -796,8 +796,8 @@ class coro_http_server { auto port_sv = std::string_view(address).substr(pos + 1); uint16_t port; - auto [ptr, ec] = - std::from_chars(port_sv.begin(), port_sv.end(), port, 10); + auto [ptr, ec] = std::from_chars( + port_sv.data(), port_sv.data() + port_sv.size(), port, 10); if (ec != std::errc{}) { address_ = std::move(address); return;