From c4ce5127c605d4275899ef552fe42970bbd2cb2b Mon Sep 17 00:00:00 2001 From: Richard Holland Date: Mon, 24 Oct 2022 11:51:47 +0000 Subject: [PATCH 1/3] Allow port numbers be be specified using a either a colon or a space (e.g 1.2.3.4:51235 and 1.2.3.4 51235) --- src/ripple/core/impl/Config.cpp | 14 +++++++++ src/ripple/net/impl/RPCCall.cpp | 22 ++++++++++--- src/ripple/rpc/handlers/Connect.cpp | 8 +++-- src/test/core/Config_test.cpp | 48 +++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index e53d9688392..572b545e2e0 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #if BOOST_OS_WINDOWS @@ -469,6 +470,19 @@ Config::loadFromString(std::string const& fileContents) if (auto s = getIniFileSection(secConfig, SECTION_SNTP)) SNTP_SERVERS = *s; + // if the user has specified ip:port then replace : with a space. + { + auto replaceColons = [](std::vector& strVec) { + const std::regex e(":([0-9]+)$"); + + for (size_t i = 0; i < strVec.size(); ++i) + strVec[i] = std::regex_replace(strVec[i], e, " $1"); + }; + + replaceColons(IPS_FIXED); + replaceColons(IPS); + } + { std::string dbPath; if (getSingleSection(secConfig, "database_path", dbPath, j_)) diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index 334ca8693e3..2c84814a381 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -482,17 +482,31 @@ class RPCParser return jvRequest; } - // connect [port] + // connect [port] Json::Value parseConnect(Json::Value const& jvParams) { Json::Value jvRequest(Json::objectValue); - - jvRequest[jss::ip] = jvParams[0u].asString(); - + std::string ip = jvParams[0u].asString(); if (jvParams.size() == 2) + { + jvRequest[jss::ip] = ip; jvRequest[jss::port] = jvParams[1u].asUInt(); + return jvRequest; + } + + // handle case where there is one argument of the form ip:port + std::size_t colon = ip.find_last_of(":"); + if (colon != std::string::npos) + { + jvRequest[jss::ip] = std::string{ip, 0, colon}; + jvRequest[jss::port] = + Json::Value{std::string{ip, colon + 1}}.asUInt(); + return jvRequest; + } + // default case, no port + jvRequest[jss::ip] = ip; return jvRequest; } diff --git a/src/ripple/rpc/handlers/Connect.cpp b/src/ripple/rpc/handlers/Connect.cpp index 532e04087aa..ca567118246 100644 --- a/src/ripple/rpc/handlers/Connect.cpp +++ b/src/ripple/rpc/handlers/Connect.cpp @@ -59,13 +59,15 @@ doConnect(RPC::JsonContext& context) else iPort = DEFAULT_PEER_PORT; - auto ip = - beast::IP::Endpoint::from_string(context.params[jss::ip].asString()); + auto const ip_str = context.params[jss::ip].asString(); + auto ip = beast::IP::Endpoint::from_string(ip_str); if (!is_unspecified(ip)) context.app.overlay().connect(ip.at_port(iPort)); - return RPC::makeObjectValue("connecting"); + return RPC::makeObjectValue( + "attempting connection to " + ip_str + ":" + + Json::Value{iPort}.asString()); } } // namespace ripple diff --git a/src/test/core/Config_test.cpp b/src/test/core/Config_test.cpp index da29fafaca2..28d5ad9a6fb 100644 --- a/src/test/core/Config_test.cpp +++ b/src/test/core/Config_test.cpp @@ -856,6 +856,53 @@ r.ripple.com 51235 cfg.section(SECTION_IPS_FIXED).values().size() == 2); } + void + testColons() + { + Config cfg; + /* NOTE: this string includes some explicit + * space chars in order to verify proper trimming */ + std::string toLoad(R"( +[port_rpc])" + "\x20" + R"( +# comment + # indented comment +)" + "\x20\x20" + R"( +[ips])" + "\x20" + R"( +r.ripple.com:51235 + + [ips_fixed])" + "\x20\x20" + R"( + # COMMENT + s1.ripple.com:51235 + s2.ripple.com 51235 + anotherserversansport + +)"); + cfg.loadFromString(toLoad); + BEAST_EXPECT( + cfg.exists("port_rpc") && cfg.section("port_rpc").lines().empty() && + cfg.section("port_rpc").values().empty()); + BEAST_EXPECT( + cfg.exists(SECTION_IPS) && + cfg.section(SECTION_IPS).lines().size() == 1 && + cfg.section(SECTION_IPS).values().size() == 1); + BEAST_EXPECT( + cfg.exists(SECTION_IPS_FIXED) && + cfg.section(SECTION_IPS_FIXED).lines().size() == 3 && + cfg.section(SECTION_IPS_FIXED).values().size() == 3); + BEAST_EXPECT(cfg.IPS[0] == "r.ripple.com 51235"); + BEAST_EXPECT(cfg.IPS_FIXED[0] == "s1.ripple.com 51235"); + BEAST_EXPECT(cfg.IPS_FIXED[1] == "s2.ripple.com 51235"); + BEAST_EXPECT(cfg.IPS_FIXED[2] == "anotherserversansport"); + } + void testComments() { @@ -1147,6 +1194,7 @@ r.ripple.com 51235 testSetup(true); testPort(); testWhitespace(); + testColons(); testComments(); testGetters(); testAmendment(); From 0b0d76f51306a574f761da97349c2a36b8ac4ebb Mon Sep 17 00:00:00 2001 From: Richard Holland Date: Tue, 25 Oct 2022 09:31:29 +0000 Subject: [PATCH 2/3] ensure ipv6 isn't confused for ip:port --- src/ripple/core/impl/Config.cpp | 15 ++++++++++--- src/ripple/net/impl/RPCCall.cpp | 4 ++-- src/ripple/rpc/handlers/Connect.cpp | 4 ++-- src/test/core/Config_test.cpp | 35 +++++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index 572b545e2e0..23ea693134d 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -473,10 +473,19 @@ Config::loadFromString(std::string const& fileContents) // if the user has specified ip:port then replace : with a space. { auto replaceColons = [](std::vector& strVec) { - const std::regex e(":([0-9]+)$"); - + const static std::regex e(":([0-9]+)$"); for (size_t i = 0; i < strVec.size(); ++i) - strVec[i] = std::regex_replace(strVec[i], e, " $1"); + { + // skip anything that might be an ipv6 address + if (std::count(strVec[i].begin(), strVec[i].end(), ':') != 1) + continue; + + std::string result = std::regex_replace(strVec[i], e, " $1"); + // sanity check the result of the replace, should be same length + // as input + if (result.size() == strVec[i].size()) + strVec[i] = result; + } }; replaceColons(IPS_FIXED); diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index 2c84814a381..5e5766d3ba9 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -496,9 +496,9 @@ class RPCParser } // handle case where there is one argument of the form ip:port - std::size_t colon = ip.find_last_of(":"); - if (colon != std::string::npos) + if (std::count(ip.begin(), ip.end(), ':') == 1) { + std::size_t colon = ip.find_last_of(":"); jvRequest[jss::ip] = std::string{ip, 0, colon}; jvRequest[jss::port] = Json::Value{std::string{ip, colon + 1}}.asUInt(); diff --git a/src/ripple/rpc/handlers/Connect.cpp b/src/ripple/rpc/handlers/Connect.cpp index ca567118246..0e452a36c3a 100644 --- a/src/ripple/rpc/handlers/Connect.cpp +++ b/src/ripple/rpc/handlers/Connect.cpp @@ -66,8 +66,8 @@ doConnect(RPC::JsonContext& context) context.app.overlay().connect(ip.at_port(iPort)); return RPC::makeObjectValue( - "attempting connection to " + ip_str + ":" + - Json::Value{iPort}.asString()); + "attempting connection to IP:" + ip_str + + " port: " + Json::Value{iPort}.asString()); } } // namespace ripple diff --git a/src/test/core/Config_test.cpp b/src/test/core/Config_test.cpp index 28d5ad9a6fb..b455762dea4 100644 --- a/src/test/core/Config_test.cpp +++ b/src/test/core/Config_test.cpp @@ -883,6 +883,19 @@ r.ripple.com:51235 s1.ripple.com:51235 s2.ripple.com 51235 anotherserversansport + anotherserverwithport:12 + 1.1.1.1:1 + 1.1.1.1 1 + 12.34.12.123:12345 + 12.34.12.123 12345 + :: + 2001:db8:: + ::1 + ::1:12345 + [::1]:12345 + 2001:db8:3333:4444:5555:6666:7777:8888:12345 + [2001:db8:3333:4444:5555:6666:7777:8888]:1 + )"); cfg.loadFromString(toLoad); @@ -895,12 +908,30 @@ r.ripple.com:51235 cfg.section(SECTION_IPS).values().size() == 1); BEAST_EXPECT( cfg.exists(SECTION_IPS_FIXED) && - cfg.section(SECTION_IPS_FIXED).lines().size() == 3 && - cfg.section(SECTION_IPS_FIXED).values().size() == 3); + cfg.section(SECTION_IPS_FIXED).lines().size() == 15 && + cfg.section(SECTION_IPS_FIXED).values().size() == 15); BEAST_EXPECT(cfg.IPS[0] == "r.ripple.com 51235"); + BEAST_EXPECT(cfg.IPS_FIXED[0] == "s1.ripple.com 51235"); BEAST_EXPECT(cfg.IPS_FIXED[1] == "s2.ripple.com 51235"); BEAST_EXPECT(cfg.IPS_FIXED[2] == "anotherserversansport"); + BEAST_EXPECT(cfg.IPS_FIXED[3] == "anotherserverwithport 12"); + BEAST_EXPECT(cfg.IPS_FIXED[4] == "1.1.1.1 1"); + BEAST_EXPECT(cfg.IPS_FIXED[5] == "1.1.1.1 1"); + BEAST_EXPECT(cfg.IPS_FIXED[6] == "12.34.12.123 12345"); + BEAST_EXPECT(cfg.IPS_FIXED[7] == "12.34.12.123 12345"); + + // all ipv6 should be ignored by colon replacer, howsoever formated + BEAST_EXPECT(cfg.IPS_FIXED[8] == "::"); + BEAST_EXPECT(cfg.IPS_FIXED[9] == "2001:db8::"); + BEAST_EXPECT(cfg.IPS_FIXED[10] == "::1"); + BEAST_EXPECT(cfg.IPS_FIXED[11] == "::1:12345"); + BEAST_EXPECT(cfg.IPS_FIXED[12] == "[::1]:12345"); + BEAST_EXPECT( + cfg.IPS_FIXED[13] == + "2001:db8:3333:4444:5555:6666:7777:8888:12345"); + BEAST_EXPECT( + cfg.IPS_FIXED[14] == "[2001:db8:3333:4444:5555:6666:7777:8888]:1"); } void From 5bbfcabbc7a395847e6598a61944651f4fd8118e Mon Sep 17 00:00:00 2001 From: Richard Holland Date: Mon, 19 Dec 2022 17:54:07 +0000 Subject: [PATCH 3/3] [FOLD] minor optimisations --- src/ripple/core/impl/Config.cpp | 10 +++++----- src/ripple/rpc/handlers/Connect.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index 23ea693134d..8de30c40208 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -474,17 +474,17 @@ Config::loadFromString(std::string const& fileContents) { auto replaceColons = [](std::vector& strVec) { const static std::regex e(":([0-9]+)$"); - for (size_t i = 0; i < strVec.size(); ++i) + for (auto& line : strVec) { // skip anything that might be an ipv6 address - if (std::count(strVec[i].begin(), strVec[i].end(), ':') != 1) + if (std::count(line.begin(), line.end(), ':') != 1) continue; - std::string result = std::regex_replace(strVec[i], e, " $1"); + std::string result = std::regex_replace(line, e, " $1"); // sanity check the result of the replace, should be same length // as input - if (result.size() == strVec[i].size()) - strVec[i] = result; + if (result.size() == line.size()) + line = result; } }; diff --git a/src/ripple/rpc/handlers/Connect.cpp b/src/ripple/rpc/handlers/Connect.cpp index 0e452a36c3a..ed366f64b2b 100644 --- a/src/ripple/rpc/handlers/Connect.cpp +++ b/src/ripple/rpc/handlers/Connect.cpp @@ -67,7 +67,7 @@ doConnect(RPC::JsonContext& context) return RPC::makeObjectValue( "attempting connection to IP:" + ip_str + - " port: " + Json::Value{iPort}.asString()); + " port: " + std::to_string(iPort)); } } // namespace ripple