diff --git a/builds/msvc/vs2022/libbitcoin-system.import.props b/builds/msvc/vs2022/libbitcoin-system.import.props
index 58f802c10..59ce698bc 100644
--- a/builds/msvc/vs2022/libbitcoin-system.import.props
+++ b/builds/msvc/vs2022/libbitcoin-system.import.props
@@ -49,7 +49,7 @@
- WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)
+ WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0602;%(PreprocessorDefinitions)
BOOST_JSON_NO_LIB;BOOST_CONTAINER_NO_LIB;%(PreprocessorDefinitions)
BC_STATIC;%(PreprocessorDefinitions)
diff --git a/console/main.cpp b/console/main.cpp
index f0decbf52..0a4a45c0f 100644
--- a/console/main.cpp
+++ b/console/main.cpp
@@ -79,15 +79,17 @@ BC_USE_LIBBITCOIN_MAIN
int bc::system::main(int argc, char* argv[])
{
using namespace bc;
- using namespace bc::node;
using namespace bc::system;
+ using namespace bc::network;
+ using namespace bc::node;
+ using namespace bc::server;
// en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio
std::ios_base::sync_with_stdio(false);
set_utf8_stdio();
- const server::web_pages web_server{};
- const server::explore_pages block_explorer{};
+ const web_pages web_server{};
+ const explore_pages block_explorer{};
parser metadata(chain::selection::mainnet, block_explorer, web_server);
const auto& args = const_cast(argv);
@@ -99,18 +101,7 @@ int bc::system::main(int argc, char* argv[])
symbols_path = metadata.configured.log.symbols;
#endif
-// Requires _WIN32_WINNT set to 0x0602 (defaults 0x0602 in vc++ 2022).
-#if defined(HAVE_MSC) && (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
-
- // Set low memory priority on the current process (testing).
- MEMORY_PRIORITY_INFORMATION priority{ MEMORY_PRIORITY_LOW };
- SetProcessInformation(
- GetCurrentProcess(),
- ProcessMemoryPriority,
- &priority,
- sizeof(priority));
-
-#endif
+ set_memory_priority(metadata.configured.node.memory_priority_());
executor host(metadata, cin, cout, cerr);
return host.dispatch() ? 0 : -1;
diff --git a/include/bitcoin/node/protocols/protocol_explore.hpp b/include/bitcoin/node/protocols/protocol_explore.hpp
index 376e7c81a..ceefabc0d 100644
--- a/include/bitcoin/node/protocols/protocol_explore.hpp
+++ b/include/bitcoin/node/protocols/protocol_explore.hpp
@@ -48,13 +48,9 @@ class BCN_API protocol_explore
}
protected:
- /// Receivers.
- void handle_receive_get(const code& ec,
- const network::http::method::get& request) NOEXCEPT override;
-
/// Dispatch.
- virtual bool dispatch_object(
- const network::http::request& request) NOEXCEPT;
+ bool try_dispatch_object(
+ const network::http::request& request) NOEXCEPT override;
};
} // namespace node
diff --git a/include/bitcoin/node/protocols/protocol_html.hpp b/include/bitcoin/node/protocols/protocol_html.hpp
index aea4b7efc..8cd616925 100644
--- a/include/bitcoin/node/protocols/protocol_html.hpp
+++ b/include/bitcoin/node/protocols/protocol_html.hpp
@@ -52,7 +52,11 @@ class BCN_API protocol_html
const network::http::method::get& request) NOEXCEPT override;
/// Dispatch.
- virtual bool dispatch_embedded(
+ virtual bool try_dispatch_object(
+ const network::http::request& request) NOEXCEPT;
+ virtual void dispatch_file(
+ const network::http::request& request) NOEXCEPT;
+ virtual void dispatch_embedded(
const network::http::request& request) NOEXCEPT;
/// Senders.
diff --git a/include/bitcoin/node/settings.hpp b/include/bitcoin/node/settings.hpp
index ccb38e61e..57c300eb9 100644
--- a/include/bitcoin/node/settings.hpp
+++ b/include/bitcoin/node/settings.hpp
@@ -70,9 +70,10 @@ class BCN_API settings
settings(system::chain::selection context) NOEXCEPT;
/// Properties.
- bool priority;
bool delay_inbound;
bool headers_first;
+ bool thread_priority;
+ bool memory_priority;
float allowed_deviation;
uint16_t announcement_cache;
uint16_t allocation_multiple;
@@ -91,7 +92,8 @@ class BCN_API settings
virtual size_t maximum_concurrency_() const NOEXCEPT;
virtual network::steady_clock::duration sample_period() const NOEXCEPT;
virtual network::wall_clock::duration currency_window() const NOEXCEPT;
- virtual network::thread_priority priority_() const NOEXCEPT;
+ virtual network::processing_priority thread_priority_() const NOEXCEPT;
+ virtual network::memory_priority memory_priority_() const NOEXCEPT;
};
} // namespace node
diff --git a/src/chasers/chaser_validate.cpp b/src/chasers/chaser_validate.cpp
index 4ac114b4d..a6f5ad0aa 100644
--- a/src/chasers/chaser_validate.cpp
+++ b/src/chasers/chaser_validate.cpp
@@ -37,7 +37,8 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
// Independent threadpool and strand (base class strand uses network pool).
chaser_validate::chaser_validate(full_node& node) NOEXCEPT
: chaser(node),
- threadpool_(node.config().node.threads_(), node.config().node.priority_()),
+ threadpool_(node.config().node.threads_(),
+ node.config().node.thread_priority_()),
independent_strand_(threadpool_.service().get_executor()),
subsidy_interval_(node.config().bitcoin.subsidy_interval_blocks),
initial_subsidy_(node.config().bitcoin.initial_subsidy()),
diff --git a/src/parser.cpp b/src/parser.cpp
index c5d161f7e..8f336ce91 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -1004,9 +1004,14 @@ options_metadata parser::load_settings() THROWS
"The number of threads in the validation threadpool, defaults to '32'."
)
(
- "node.priority",
- value(&configured.node.priority),
- "Set the validation threadpool to high priority, defaults to 'true'."
+ "node.thread_priority",
+ value(&configured.node.thread_priority),
+ "Set validation threads to high processing priority, defaults to 'true'."
+ )
+ (
+ "node.memory_priority",
+ value(&configured.node.memory_priority),
+ "Set the process to high memory priority, defaults to 'true'."
)
(
"node.delay_inbound",
diff --git a/src/protocols/protocol_explore.cpp b/src/protocols/protocol_explore.cpp
index 7d332fb3a..016b7fe79 100644
--- a/src/protocols/protocol_explore.cpp
+++ b/src/protocols/protocol_explore.cpp
@@ -24,95 +24,19 @@ namespace libbitcoin {
namespace node {
#define CLASS protocol_explore
-
-using namespace boost::json;
-using namespace std::placeholders;
-using namespace network::http;
+
using namespace system;
+using namespace network::http;
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
-// Handle get method.
-// ----------------------------------------------------------------------------
-
-void protocol_explore::handle_receive_get(const code& ec,
- const method::get& request) NOEXCEPT
-{
- BC_ASSERT(stranded());
-
- if (stopped(ec))
- return;
-
- // Enforce http origin policy (requires configured hosts).
- if (!is_allowed_origin(*request, request->version()))
- {
- send_forbidden(*request);
- return;
- }
-
- // Enforce http host header (if any hosts are configured).
- if (!is_allowed_host(*request, request->version()))
- {
- send_bad_host(*request);
- return;
- }
-
- // Dispatch object with specified encoding.
- if (dispatch_object(*request))
- return;
-
- // Embedded page site.
- if (dispatch_embedded(*request))
- return;
-
- // Empty path implies malformed target (terminal).
- auto path = to_local_path(request->target());
- if (path.empty())
- {
- send_bad_target(*request);
- return;
- }
-
- // If no file extension it's REST on the single/default html page.
- if (!path.has_extension())
- {
- path = to_local_path();
-
- // Default html page (e.g. index.html) is not configured.
- if (path.empty())
- {
- send_not_implemented(*request);
- return;
- }
- }
-
- // Get the single/default or explicitly requested page.
- auto file = get_file_body(path);
- if (!file.is_open())
- {
- send_not_found(*request);
- return;
- }
-
- send_file(*request, std::move(file),
- file_mime_type(path, mime_type::application_octet_stream));
-}
-
// Dispatch.
// ----------------------------------------------------------------------------
-bool protocol_explore::dispatch_object(
- const network::http::request& request) NOEXCEPT
+bool protocol_explore::try_dispatch_object(const request& request) NOEXCEPT
{
- const auto target = request.target();
- if (!is_origin_form(target))
- {
- send_bad_target(request);
- return true;
- }
-
wallet::uri uri{};
- if (!uri.decode(target))
+ if (!uri.decode(request.target()))
{
send_bad_target(request);
return true;
diff --git a/src/protocols/protocol_html.cpp b/src/protocols/protocol_html.cpp
index 22bcb125d..d7477cb0e 100644
--- a/src/protocols/protocol_html.cpp
+++ b/src/protocols/protocol_html.cpp
@@ -41,7 +41,14 @@ void protocol_html::handle_receive_get(const code& ec,
if (stopped(ec))
return;
- // Enforce http origin policy (requires configured hosts).
+ // Enforce http origin form for get.
+ if (!is_origin_form(request->target()))
+ {
+ send_bad_target(*request);
+ return;
+ }
+
+ // Enforce http origin policy (if any origins are configured).
if (!is_allowed_origin(*request, request->version()))
{
send_forbidden(*request);
@@ -55,67 +62,99 @@ void protocol_html::handle_receive_get(const code& ec,
return;
}
- // Embedded page site.
- if (dispatch_embedded(*request))
+ // Always try API dispatch, false if unhandled.
+ if (try_dispatch_object(*request))
return;
- // Empty path implies malformed target (terminal).
- const auto path = to_local_path(request->target());
- if (path.empty())
+ // Require file system dispatch if path is configured (always handles).
+ if (!options_.path.empty())
{
- // TODO: split out sanitize from canonicalize so that this can return
- // send_not_found() when the request is sanitary but not found.
- send_bad_target(*request);
+ dispatch_file(*request);
return;
}
- // Not open implies file not found (non-terminal).
- auto file = get_file_body(path);
- if (!file.is_open())
+ // Require embedded dispatch if site is configured (always handles).
+ if (options_.pages.enabled())
{
- send_not_found(*request);
+ dispatch_embedded(*request);
return;
}
- send_file(*request, std::move(file),
- file_mime_type(path, mime_type::application_octet_stream));
+ // Neither site is enabled and object dispatch doesn't support.
+ send_not_implemented(*request);
}
// Dispatch.
// ----------------------------------------------------------------------------
-bool protocol_html::dispatch_embedded(const request& request) NOEXCEPT
+bool protocol_html::try_dispatch_object(const request&) NOEXCEPT
{
- // False only if not enabled, otherwise handled below.
- if (!options_.pages.enabled())
- return false;
+ return false;
+}
+void protocol_html::dispatch_embedded(const request& request) NOEXCEPT
+{
const auto& pages = config().server.explore.pages;
switch (const auto mime = file_mime_type(to_path(request.target())))
{
case mime_type::text_css:
send_span(request, pages.css(), mime);
- return true;
+ break;
case mime_type::text_html:
send_span(request, pages.html(), mime);
- return true;
+ break;
case mime_type::application_javascript:
send_span(request, pages.ecma(), mime);
- return true;
+ break;
case mime_type::font_woff:
case mime_type::font_woff2:
send_span(request, pages.font(), mime);
- return true;
+ break;
case mime_type::image_png:
case mime_type::image_gif:
case mime_type::image_jpeg:
send_span(request, pages.icon(), mime);
- return true;
+ break;
default:
- return false;
+ send_not_found(request);
}
}
+void protocol_html::dispatch_file(const request& request) NOEXCEPT
+{
+ // Empty path implies malformed target (terminal).
+ auto path = to_local_path(request.target());
+ if (path.empty())
+ {
+ send_bad_target(request);
+ return;
+ }
+
+ // If no file extension it's REST on the single/default html page.
+ if (!path.has_extension())
+ {
+ path = to_local_path();
+
+ // Default html page (e.g. index.html) is not configured.
+ if (path.empty())
+ {
+ send_not_implemented(request);
+ return;
+ }
+ }
+
+ // Get the single/default or explicitly requested page.
+ auto file = get_file_body(path);
+ if (!file.is_open())
+ {
+ send_not_found(request);
+ return;
+ }
+
+ const auto octet_stream = mime_type::application_octet_stream;
+ send_file(request, std::move(file), file_mime_type(path, octet_stream));
+}
+
// Senders.
// ----------------------------------------------------------------------------
diff --git a/src/settings.cpp b/src/settings.cpp
index 21d5584a9..bec9292f4 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -81,9 +81,10 @@ std::filesystem::path settings::events_file() const NOEXCEPT
namespace node {
settings::settings() NOEXCEPT
- : priority{ true },
- delay_inbound{ true },
+ : delay_inbound{ true },
headers_first{ true },
+ memory_priority{ true },
+ thread_priority{ true },
allowed_deviation{ 1.5 },
announcement_cache{ 42 },
allocation_multiple{ 20 },
@@ -129,10 +130,20 @@ network::wall_clock::duration settings::currency_window() const NOEXCEPT
return network::minutes(currency_window_minutes);
}
-network::thread_priority settings::priority_() const NOEXCEPT
+network::processing_priority settings::thread_priority_() const NOEXCEPT
{
- return priority ? network::thread_priority::high :
- network::thread_priority::normal;
+ // medium is "normal" (os default), so true is a behavior change.
+ // highest is too much, as it makes the opreating system UI unresponsive.
+ return thread_priority ? network::processing_priority::high :
+ network::processing_priority::medium;
+}
+
+network::memory_priority settings::memory_priority_() const NOEXCEPT
+{
+ // highest is "normal" (os default), so false is a behavior change.
+ // highest is the OS default, so far low does not have a noticeable effect.
+ return memory_priority ? network::memory_priority::highest :
+ network::memory_priority::low;
}
} // namespace node
diff --git a/test/settings.cpp b/test/settings.cpp
index 3dba405b2..119f2eb8b 100644
--- a/test/settings.cpp
+++ b/test/settings.cpp
@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(settings__node__default_context__expected)
using namespace network;
const node::settings node{};
- BOOST_REQUIRE_EQUAL(node.priority, true);
+ BOOST_REQUIRE_EQUAL(node.thread_priority, true);
BOOST_REQUIRE_EQUAL(node.delay_inbound, true);
BOOST_REQUIRE_EQUAL(node.headers_first, true);
BOOST_REQUIRE_EQUAL(node.allowed_deviation, 1.5);
@@ -77,7 +77,8 @@ BOOST_AUTO_TEST_CASE(settings__node__default_context__expected)
BOOST_REQUIRE_EQUAL(node.maximum_concurrency_(), 50'000_size);
BOOST_REQUIRE(node.sample_period() == steady_clock::duration(seconds(10)));
BOOST_REQUIRE(node.currency_window() == steady_clock::duration(minutes(60)));
- BOOST_REQUIRE(node.priority_() == network::thread_priority::high);
+ BOOST_REQUIRE(node.thread_priority_() == network::processing_priority::high);
+ BOOST_REQUIRE(node.memory_priority_() == network::memory_priority::highest);
}
// [server]