summaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authoraneporada <[email protected]>2026-03-21 08:25:00 +0300
committeraneporada <[email protected]>2026-03-21 08:41:45 +0300
commiteebdd2a68c351422f9182df76378a33d07f7a449 (patch)
treea269722bb9f009de10324d225b68a3ec75ba6454 /library/cpp
parent0ced6e47d9d653fc10192fac213220ef1b7c860e (diff)
Support loopback-only binds in messagebus
commit_hash:1acc39366e0b54658fb2847e848a9bc3b7a8b8a6
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/messagebus/network.cpp60
-rw-r--r--library/cpp/messagebus/network.h1
-rw-r--r--library/cpp/messagebus/network_ut.cpp36
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());