Skip to content

Commit 9eedf5f

Browse files
authored
Merge pull request #606 from evoskuil/master
Generalize explore routing, factor out new [peer] config section.
2 parents efbd679 + eaa0e84 commit 9eedf5f

File tree

5 files changed

+135
-131
lines changed

5 files changed

+135
-131
lines changed

include/bitcoin/server/parsers/explore_query.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,28 @@
2424
namespace libbitcoin {
2525
namespace server {
2626

27+
// Query string tokens.
28+
namespace token
29+
{
30+
// Names.
31+
constexpr auto turbo = "turbo";
32+
constexpr auto format = "format";
33+
constexpr auto witness = "witness";
34+
35+
// Boolean values.
36+
constexpr auto true_ = "true";
37+
constexpr auto false_ = "false";
38+
39+
// Format values.
40+
namespace formats
41+
{
42+
constexpr auto html = "html";
43+
constexpr auto text = "text";
44+
constexpr auto json = "json";
45+
constexpr auto data = "data";
46+
}
47+
}
48+
2749
BCS_API bool explore_query(network::rpc::request_t& out,
2850
const network::http::request& request) NOEXCEPT;
2951

src/parser.cpp

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -509,143 +509,140 @@ options_metadata parser::load_settings() THROWS
509509
"The minimum number of threads in the network threadpool, defaults to '16'."
510510
)
511511
(
512-
"network.address_upper",
512+
"network.retry_timeout_seconds",
513+
value<uint32_t>(&configured.network.retry_timeout_seconds),
514+
"The time delay for failed connection retry, defaults to '1'."
515+
)
516+
(
517+
"network.connect_timeout_seconds",
518+
value<uint32_t>(&configured.network.connect_timeout_seconds),
519+
"The time limit for connection establishment, defaults to '5'."
520+
)
521+
(
522+
"network.rate_limit",
523+
value<uint32_t>(&configured.network.rate_limit),
524+
"The peer download rate limit (not implemented)."
525+
)
526+
(
527+
"network.blacklist",
528+
value<network::config::authorities>(&configured.network.blacklists),
529+
"IP address to disallow, allows all others, multiple allowed."
530+
)
531+
(
532+
"network.whitelist",
533+
value<network::config::authorities>(&configured.network.whitelists),
534+
"IP address to allow, prohibits all others, multiple allowed."
535+
)
536+
537+
/* [peer] */
538+
(
539+
"peer.address_upper",
513540
value<uint16_t>(&configured.network.address_upper),
514541
"The upper bound for address selection divisor, defaults to '10'."
515542
)
516543
(
517-
"network.address_lower",
544+
"peer.address_lower",
518545
value<uint16_t>(&configured.network.address_lower),
519546
"The lower bound for address selection divisor, defaults to '5'."
520547
)
521548
(
522-
"network.protocol_maximum",
549+
"peer.protocol_maximum",
523550
value<uint32_t>(&configured.network.protocol_maximum),
524551
"The maximum network protocol version, defaults to '70012'."
525552
)
526553
(
527-
"network.protocol_minimum",
554+
"peer.protocol_minimum",
528555
value<uint32_t>(&configured.network.protocol_minimum),
529556
"The minimum network protocol version, defaults to '31800'."
530557
)
531558
(
532-
"network.services_maximum",
559+
"peer.services_maximum",
533560
value<uint64_t>(&configured.network.services_maximum),
534561
"The maximum services exposed by network connections, defaults to '9' (full node, witness)."
535562
)
536563
(
537-
"network.services_minimum",
564+
"peer.services_minimum",
538565
value<uint64_t>(&configured.network.services_minimum),
539566
"The minimum services exposed by network connections, defaults to '9' (full node, witness)."
540567
)
541568
(
542-
"network.invalid_services",
569+
"peer.invalid_services",
543570
value<uint64_t>(&configured.network.invalid_services),
544571
"The advertised services that cause a peer to be dropped, defaults to '176'."
545572
)
546573
(
547-
"network.enable_address",
574+
"peer.enable_address",
548575
value<bool>(&configured.network.enable_address),
549576
"Enable address messages, defaults to 'true'."
550577
)
551578
(
552-
"network.enable_address_v2",
579+
"peer.enable_address_v2",
553580
value<bool>(&configured.network.enable_address_v2),
554581
"Enable address v2 messages, defaults to 'false'."
555582
)
556583
(
557-
"network.enable_witness_tx",
584+
"peer.enable_witness_tx",
558585
value<bool>(&configured.network.enable_witness_tx),
559586
"Enable witness transaction identifier relay, defaults to 'false'."
560587
)
561588
(
562-
"network.enable_compact",
589+
"peer.enable_compact",
563590
value<bool>(&configured.network.enable_compact),
564591
"Enable enable compact block messages, defaults to 'false'."
565592
)
566593
(
567-
"network.enable_alert",
594+
"peer.enable_alert",
568595
value<bool>(&configured.network.enable_alert),
569596
"Enable alert messages, defaults to 'false'."
570597
)
571598
(
572-
"network.enable_reject",
599+
"peer.enable_reject",
573600
value<bool>(&configured.network.enable_reject),
574601
"Enable reject messages, defaults to 'false'."
575602
)
576603
(
577-
"network.enable_relay",
604+
"peer.enable_relay",
578605
value<bool>(&configured.network.enable_relay),
579606
"Enable transaction relay, defaults to 'true'."
580607
)
581608
(
582-
"network.validate_checksum",
609+
"peer.validate_checksum",
583610
value<bool>(&configured.network.validate_checksum),
584611
"Validate the checksum of network messages, defaults to 'false'."
585612
)
586613
(
587-
"network.identifier",
614+
"peer.identifier",
588615
value<uint32_t>(&configured.network.identifier),
589616
"The magic number for message headers, defaults to '3652501241'."
590617
)
591618
(
592-
"network.retry_timeout_seconds",
593-
value<uint32_t>(&configured.network.retry_timeout_seconds),
594-
"The time delay for failed connection retry, defaults to '1'."
595-
)
596-
(
597-
"network.connect_timeout_seconds",
598-
value<uint32_t>(&configured.network.connect_timeout_seconds),
599-
"The time limit for connection establishment, defaults to '5'."
600-
)
601-
(
602-
"network.handshake_timeout_seconds",
619+
"peer.handshake_timeout_seconds",
603620
value<uint32_t>(&configured.network.handshake_timeout_seconds),
604621
"The time limit to complete the connection handshake, defaults to '15'."
605622
)
606623
(
607-
"network.channel_heartbeat_minutes",
624+
"peer.channel_heartbeat_minutes",
608625
value<uint32_t>(&configured.network.channel_heartbeat_minutes),
609626
"The time between ping messages, defaults to '5'."
610627
)
611628
(
612-
"network.maximum_skew_minutes",
629+
"peer.maximum_skew_minutes",
613630
value<uint32_t>(&configured.network.maximum_skew_minutes),
614631
"The maximum allowable channel clock skew, defaults to '120'."
615632
)
616633
(
617-
"network.rate_limit",
618-
value<uint32_t>(&configured.network.rate_limit),
619-
"The peer download rate limit in bytes per second, defaults to 1024 (not implemented)."
620-
)
621-
(
622-
"network.user_agent",
634+
"peer.user_agent",
623635
value<std::string>(&configured.network.user_agent),
624636
"The node user agent string, defaults to '" BC_USER_AGENT "'."
625637
)
626638
(
627-
"network.path",
639+
"peer.path",
628640
value<std::filesystem::path>(&configured.network.path),
629641
"The peer address cache file directory, defaults to empty."
630642
)
631-
(
632-
"network.blacklist",
633-
value<network::config::authorities>(&configured.network.blacklists),
634-
"IP address to disallow as a peer, multiple allowed."
635-
)
636-
(
637-
"network.whitelist",
638-
value<network::config::authorities>(&configured.network.whitelists),
639-
"IP address to allow as a peer, multiple allowed."
640-
)
641643

642644
/* [outbound] */
643645
////(
644-
//// "outbound.secure",
645-
//// value<bool>(&configured.network.outbound.secure),
646-
//// "Require transport layer security, defaults to 'false' (not implemented)."
647-
////)
648-
////(
649646
//// "outbound.bind",
650647
//// value<network::config::authorities>(&configured.network.outbound.binds),
651648
//// "IP address to bind for load balancing, multiple allowed (not implemented)."
@@ -1675,7 +1672,9 @@ options_metadata parser::load_settings() THROWS
16751672
return description;
16761673
}
16771674

1675+
BC_PUSH_WARNING(NO_ARRAY_TO_POINTER_DECAY)
16781676
bool parser::parse(int argc, const char* argv[], std::ostream& error) THROWS
1677+
BC_POP_WARNING()
16791678
{
16801679
try
16811680
{

src/parsers/explore_query.cpp

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ using namespace network::http;
3030
BC_PUSH_WARNING(NO_ARRAY_INDEXING)
3131
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
3232

33+
inline bool is_true(const std::string& value) NOEXCEPT
34+
{
35+
return value == token::true_;
36+
}
37+
38+
inline bool is_false(const std::string& value) NOEXCEPT
39+
{
40+
return value == token::false_;
41+
}
42+
43+
inline void set_media(rpc::object_t& params, media_type media) NOEXCEPT
44+
{
45+
params["media"] = to_value(media);
46+
}
47+
3348
bool explore_query(rpc::request_t& out, const request& request) NOEXCEPT
3449
{
3550
wallet::uri uri{};
@@ -41,70 +56,59 @@ bool explore_query(rpc::request_t& out, const request& request) NOEXCEPT
4156
constexpr auto json = media_type::application_json;
4257
constexpr auto data = media_type::application_octet_stream;
4358

44-
// TODO: reject invalid format.
45-
auto query = uri.decode_query();
46-
const auto format = query["format"];
47-
59+
// Caller must have provided a request.params object.
4860
if (!out.params.has_value() ||
4961
!std::holds_alternative<rpc::object_t>(out.params.value()))
5062
return false;
5163

64+
auto query = uri.decode_query();
5265
auto& params = std::get<rpc::object_t>(out.params.value());
5366

54-
// Validate proper witness bool value if set.
55-
const auto witness = query.find("witness");
56-
if (witness != query.end())
67+
// Witness is optional<true> (where applicable), so only set if false.
68+
if (const auto witness = query.find(token::witness); witness != query.end())
5769
{
58-
if (witness->second != "true" && witness->second != "false")
70+
if (is_false(witness->second))
71+
params[token::witness] = false;
72+
else if (!is_true(witness->second))
5973
return false;
60-
61-
// Witness is optional<true> (where applicable), so only set if false.
62-
if (witness->second == "false")
63-
params["witness"] = false;
6474
}
6575

66-
// Validate proper turbo bool value if set.
67-
const auto turbo = query.find("turbo");
68-
if (turbo != query.end())
76+
// Turbo is optional<true> (where applicable), so only set if false.
77+
if (const auto turbo = query.find(token::turbo); turbo != query.end())
6978
{
70-
if (turbo->second != "true" && turbo->second != "false")
79+
if (is_false(turbo->second))
80+
params[token::turbo] = false;
81+
else if (!is_true(turbo->second))
7182
return false;
72-
73-
// Turbo is optional<true> (where applicable), so only set if false.
74-
if (turbo->second == "false")
75-
params["turbo"] = false;
7683
}
7784

85+
const auto format = query[token::format];
7886
const auto accepts = to_media_types((request)[field::accept]);
7987

80-
if (contains(accepts, text) || format == "text")
81-
{
82-
params["media"] = to_value(text);
83-
return true;
84-
}
85-
86-
if (contains(accepts, data) || format == "data")
87-
{
88-
params["media"] = to_value(data);
89-
return true;
90-
}
91-
92-
////// Default format to json.
93-
////params["media"] = to_value(json);
94-
////return true;
95-
96-
if (contains(accepts, json) || format == "json")
97-
{
98-
params["media"] = to_value(json);
99-
return true;
100-
}
101-
102-
if (contains(accepts, html) || format == "html")
103-
params["media"] = to_value(html);
88+
// Prioritize query string format over http headers.
89+
if (format == token::formats::json)
90+
set_media(params, json);
91+
else if (format == token::formats::text)
92+
set_media(params, text);
93+
else if (format == token::formats::data)
94+
set_media(params, data);
95+
else if (format == token::formats::html)
96+
set_media(params, html);
97+
98+
// Priotize: json, html, text, data (ignores accept priorities).
99+
else if (contains(accepts, json))
100+
set_media(params, json);
101+
else if (contains(accepts, html))
102+
set_media(params, html);
103+
else if (contains(accepts, text))
104+
set_media(params, text);
105+
else if (contains(accepts, data))
106+
set_media(params, data);
107+
else
108+
return false;
104109

105-
// Not dispatchable (media is html or undefined).
106-
// TODO: differentiate return of false (error) vs. false (continue).
107-
return false;
110+
// Media type has been set.
111+
return true;
108112
}
109113

110114
media_type get_media(const rpc::request_t& model) NOEXCEPT

src/protocols/protocol_explore.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,19 +139,18 @@ bool protocol_explore::try_dispatch_object(const http::request& request) NOEXCEP
139139
return !ec;
140140
}
141141

142-
// TODO: differentiate return of false (error) vs. false (continue).
143-
if (explore_query(model, request))
142+
if (!explore_query(model, request))
144143
{
145-
if (const auto ec = dispatcher_.notify(model))
146-
send_internal_server_error(ec, request);
147-
144+
send_not_acceptable(request);
148145
return true;
149146
}
150147

151148
if (get_media(model) == http::media_type::text_html)
152149
return false;
153150

154-
send_not_acceptable(request);
151+
if (const auto ec = dispatcher_.notify(model))
152+
send_internal_server_error(ec, request);
153+
155154
return true;
156155
}
157156

0 commit comments

Comments
 (0)