diff options
| author | aneporada <[email protected]> | 2026-03-21 08:25:00 +0300 |
|---|---|---|
| committer | aneporada <[email protected]> | 2026-03-21 08:41:45 +0300 |
| commit | eebdd2a68c351422f9182df76378a33d07f7a449 (patch) | |
| tree | a269722bb9f009de10324d225b68a3ec75ba6454 /library/cpp | |
| parent | 0ced6e47d9d653fc10192fac213220ef1b7c860e (diff) | |
Support loopback-only binds in messagebus
commit_hash:1acc39366e0b54658fb2847e848a9bc3b7a8b8a6
Diffstat (limited to 'library/cpp')
| -rw-r--r-- | library/cpp/messagebus/network.cpp | 60 | ||||
| -rw-r--r-- | library/cpp/messagebus/network.h | 1 | ||||
| -rw-r--r-- | library/cpp/messagebus/network_ut.cpp | 36 |
3 files changed, 72 insertions, 25 deletions
diff --git a/library/cpp/messagebus/network.cpp b/library/cpp/messagebus/network.cpp index a4afafa94ee..6ce1fc7f517 100644 --- a/library/cpp/messagebus/network.cpp +++ b/library/cpp/messagebus/network.cpp @@ -10,7 +10,7 @@ using namespace NBus; using namespace NBus::NPrivate; namespace { - TBindResult BindOnPortProto(int port, int af, bool reusePort) { + TBindResult BindOnPortProto(int port, int af, bool reusePort, bool loopback) { Y_ABORT_UNLESS(af == AF_INET || af == AF_INET6, "wrong af"); SOCKET fd = ::socket(af, SOCK_STREAM, 0); @@ -42,10 +42,11 @@ namespace { if (af == AF_INET) { len = sizeof(sockaddr_in); ((sockaddr_in*)sa)->sin_port = HostToInet((ui16)port); - ((sockaddr_in*)sa)->sin_addr.s_addr = INADDR_ANY; + ((sockaddr_in*)sa)->sin_addr.s_addr = HostToInet(loopback ? INADDR_LOOPBACK : INADDR_ANY); } else { len = sizeof(sockaddr_in6); ((sockaddr_in6*)sa)->sin6_port = HostToInet((ui16)port); + ((sockaddr_in6*)sa)->sin6_addr = loopback ? in6addr_loopback : in6addr_any; } if (af == AF_INET6) { @@ -73,9 +74,9 @@ namespace { return r; } - TMaybe<TBindResult> TryBindOnPortProto(int port, int af, bool reusePort) { + TMaybe<TBindResult> TryBindOnPortProto(int port, int af, bool reusePort, bool loopback) { try { - return {BindOnPortProto(port, af, reusePort)}; + return {BindOnPortProto(port, af, reusePort, loopback)}; } catch (const TSystemError&) { return {}; } @@ -91,35 +92,44 @@ namespace { r.second.emplace_back(std::move(r2)); return r; } -} - -std::pair<unsigned, TVector<TBindResult>> NBus::BindOnPort(int port, bool reusePort) { - std::pair<unsigned, TVector<TBindResult>> r; - r.second.reserve(2); - if (port != 0) { - return AggregateBindResults(BindOnPortProto(port, AF_INET, reusePort), - BindOnPortProto(port, AF_INET6, reusePort)); - } + std::pair<unsigned, TVector<TBindResult>> DoBindOnPort(int port, bool reusePort, bool loopback) { + std::pair<unsigned, TVector<TBindResult>> r; + r.second.reserve(2); - // use nothrow versions in cycle - for (int i = 0; i < 1000; ++i) { - TMaybe<TBindResult> in4 = TryBindOnPortProto(0, AF_INET, reusePort); - if (!in4) { - continue; + if (port != 0) { + return AggregateBindResults(BindOnPortProto(port, AF_INET, reusePort, loopback), + BindOnPortProto(port, AF_INET6, reusePort, loopback)); } - TMaybe<TBindResult> in6 = TryBindOnPortProto(in4->Addr.GetPort(), AF_INET6, reusePort); - if (!in6) { - continue; + // use nothrow versions in cycle + for (int i = 0; i < 1000; ++i) { + TMaybe<TBindResult> in4 = TryBindOnPortProto(0, AF_INET, reusePort, loopback); + if (!in4) { + continue; + } + + TMaybe<TBindResult> in6 = TryBindOnPortProto(in4->Addr.GetPort(), AF_INET6, reusePort, loopback); + if (!in6) { + continue; + } + + return AggregateBindResults(std::move(*in4), std::move(*in6)); } - return AggregateBindResults(std::move(*in4), std::move(*in6)); + TBindResult in4 = BindOnPortProto(0, AF_INET, reusePort, loopback); + TBindResult in6 = BindOnPortProto(in4.Addr.GetPort(), AF_INET6, reusePort, loopback); + return AggregateBindResults(std::move(in4), std::move(in6)); } - TBindResult in4 = BindOnPortProto(0, AF_INET, reusePort); - TBindResult in6 = BindOnPortProto(in4.Addr.GetPort(), AF_INET6, reusePort); - return AggregateBindResults(std::move(in4), std::move(in6)); +} // namespace + +std::pair<unsigned, TVector<TBindResult>> NBus::BindOnPort(int port, bool reusePort) { + return DoBindOnPort(port, reusePort, /* loopback = */ false); +} + +std::pair<unsigned, TVector<TBindResult>> NBus::BindOnLoopbackPort(int port, bool reusePort) { + return DoBindOnPort(port, reusePort, /* loopback = */ true); } void NBus::NPrivate::SetSockOptTcpCork(SOCKET s, bool value) { diff --git a/library/cpp/messagebus/network.h b/library/cpp/messagebus/network.h index cc4bd76ea31..b63dce3741d 100644 --- a/library/cpp/messagebus/network.h +++ b/library/cpp/messagebus/network.h @@ -24,5 +24,6 @@ namespace NBus { }; std::pair<unsigned, TVector<TBindResult>> BindOnPort(int port, bool reusePort); + std::pair<unsigned, TVector<TBindResult>> BindOnLoopbackPort(int port, bool reusePort); } diff --git a/library/cpp/messagebus/network_ut.cpp b/library/cpp/messagebus/network_ut.cpp index f1798419db2..80ac410397c 100644 --- a/library/cpp/messagebus/network_ut.cpp +++ b/library/cpp/messagebus/network_ut.cpp @@ -4,6 +4,8 @@ #include <library/cpp/messagebus/test/helper/fixed_port.h> +#include <util/network/address.h> + using namespace NBus; using namespace NBus::NPrivate; using namespace NBus::NTest; @@ -29,6 +31,11 @@ namespace { throw 1; } } + + TString GetLocalAddr(SOCKET sock) { + auto addr = NAddr::GetSockAddr(sock); + return NAddr::PrintHost(*addr); + } } Y_UNIT_TEST_SUITE(Network) { @@ -42,6 +49,21 @@ Y_UNIT_TEST_SUITE(Network) { for (TVector<TBindResult>::iterator i = r.begin(); i != r.end(); ++i) { UNIT_ASSERT_VALUES_EQUAL(i->Addr.GetPort(), GetSockPort(i->Socket->operator SOCKET())); + UNIT_ASSERT_VALUES_EQUAL(i == r.begin() ? "0.0.0.0" : "::", GetLocalAddr(i->Socket->operator SOCKET())); + } + } + + Y_UNIT_TEST(BindOnLoopbackPortConcrete) { + if (!IsFixedPortTestAllowed()) { + return; + } + + TVector<TBindResult> r = BindOnLoopbackPort(FixedPort, false).second; + UNIT_ASSERT_VALUES_EQUAL(size_t(2), r.size()); + + for (TVector<TBindResult>::iterator i = r.begin(); i != r.end(); ++i) { + UNIT_ASSERT_VALUES_EQUAL(i->Addr.GetPort(), GetSockPort(i->Socket->operator SOCKET())); + UNIT_ASSERT_VALUES_EQUAL(i == r.begin() ? "127.0.0.1" : "::1", GetLocalAddr(i->Socket->operator SOCKET())); } } @@ -52,6 +74,20 @@ Y_UNIT_TEST_SUITE(Network) { for (TVector<TBindResult>::iterator i = r.begin(); i != r.end(); ++i) { UNIT_ASSERT_VALUES_EQUAL(i->Addr.GetPort(), GetSockPort(i->Socket->operator SOCKET())); UNIT_ASSERT(i->Addr.GetPort() > 0); + UNIT_ASSERT_VALUES_EQUAL(i == r.begin() ? "0.0.0.0" : "::", GetLocalAddr(i->Socket->operator SOCKET())); + } + + UNIT_ASSERT_VALUES_EQUAL(r.at(0).Addr.GetPort(), r.at(1).Addr.GetPort()); + } + + Y_UNIT_TEST(BindOnLoopbackPortRandom) { + TVector<TBindResult> r = BindOnLoopbackPort(0, false).second; + UNIT_ASSERT_VALUES_EQUAL(size_t(2), r.size()); + + for (TVector<TBindResult>::iterator i = r.begin(); i != r.end(); ++i) { + UNIT_ASSERT_VALUES_EQUAL(i->Addr.GetPort(), GetSockPort(i->Socket->operator SOCKET())); + UNIT_ASSERT(i->Addr.GetPort() > 0); + UNIT_ASSERT_VALUES_EQUAL(i == r.begin() ? "127.0.0.1" : "::1", GetLocalAddr(i->Socket->operator SOCKET())); } UNIT_ASSERT_VALUES_EQUAL(r.at(0).Addr.GetPort(), r.at(1).Addr.GetPort()); |
