mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-03 04:22:43 +08:00
[feat] add configurable all-interface IPv4 listening, refs #129
This commit is contained in:
@@ -25,7 +25,8 @@ constexpr const char* kPath = "/crossdesk/lan/v2";
|
||||
constexpr const char* kProtocol = "crossdesk.lan.v2";
|
||||
void ValidateListener(const std::string& address, unsigned port) {
|
||||
if (port > 65535) throw std::runtime_error("Invalid LAN port");
|
||||
const auto interfaces = PhysicalInterfaces();
|
||||
if (address == kAllIpv4Interfaces) return;
|
||||
const auto interfaces = LocalIpv4Interfaces();
|
||||
if (!IsIpv4(address) ||
|
||||
std::none_of(interfaces.begin(), interfaces.end(),
|
||||
[&](const auto& i) { return i.address == address; }))
|
||||
@@ -57,7 +58,7 @@ void CheckListenError(const Error& error) {
|
||||
throw std::runtime_error("LanPortPermissionDenied");
|
||||
throw std::runtime_error("Cannot listen on LAN port: " + error.message());
|
||||
}
|
||||
void CheckExistingListener(const std::string& address, unsigned port) {
|
||||
void CheckExistingEndpoint(const std::string& address, unsigned port) {
|
||||
#ifdef __APPLE__
|
||||
// BSD permits a specific-address listener alongside a wildcard listener with
|
||||
// SO_REUSEADDR. Detect that live listener without treating TIME_WAIT or our
|
||||
@@ -88,6 +89,32 @@ void CheckExistingListener(const std::string& address, unsigned port) {
|
||||
(void)port;
|
||||
#endif
|
||||
}
|
||||
void CheckExistingListener(const std::string& address, unsigned port) {
|
||||
#ifdef __APPLE__
|
||||
if (address == kAllIpv4Interfaces) {
|
||||
// BSD permits wildcard/specific overlap with SO_REUSEADDR. Probe binds on
|
||||
// each exact address to detect specific listeners without sending traffic
|
||||
// through VPN adapters which may accept connects to otherwise unused ports.
|
||||
// The final wildcard bind detects an existing wildcard listener itself.
|
||||
asio::io_context io;
|
||||
auto addresses = LocalIpv4Interfaces();
|
||||
addresses.push_back({"127.0.0.1"});
|
||||
for (const auto& interface : addresses) {
|
||||
asio::ip::tcp::acceptor probe(io);
|
||||
Error error;
|
||||
probe.open(asio::ip::tcp::v4(), error);
|
||||
CheckListenError(error);
|
||||
probe.set_option(asio::socket_base::reuse_address(true), error);
|
||||
CheckListenError(error);
|
||||
probe.bind({asio::ip::make_address_v4(interface.address),
|
||||
static_cast<unsigned short>(port)}, error);
|
||||
CheckListenError(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CheckExistingEndpoint(address, port);
|
||||
}
|
||||
std::shared_ptr<Context> TlsContext() {
|
||||
auto context = std::make_shared<Context>(Context::tls);
|
||||
if (SSL_CTX_set_min_proto_version(context->native_handle(), TLS1_3_VERSION) !=
|
||||
@@ -265,7 +292,7 @@ struct Transport::Impl {
|
||||
}
|
||||
c->local_address = local.address().to_string();
|
||||
c->remote_address = remote.address().to_string();
|
||||
const auto interfaces = PhysicalInterfaces();
|
||||
const auto interfaces = LocalIpv4Interfaces();
|
||||
if (!IsIpv4(c->remote_address) ||
|
||||
std::none_of(
|
||||
interfaces.begin(), interfaces.end(),
|
||||
|
||||
Reference in New Issue
Block a user