feat: implement TCP reachability probe for discovered domains
This commit is contained in:
@@ -172,3 +172,61 @@ std::vector<DiscoveredDomain> discoverDomains(int maxDomains) {
|
|||||||
std::vector<DiscoveredDomain> parseDomainsFromJson(const std::string& json) {
|
std::vector<DiscoveredDomain> parseDomainsFromJson(const std::string& json) {
|
||||||
return parseDomains(json);
|
return parseDomains(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simple TCP reachability probe (non-blocking connect + select)
|
||||||
|
bool probeDomain(const DiscoveredDomain& domain, int timeoutMs) {
|
||||||
|
addrinfo hints{};
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
addrinfo* res = nullptr;
|
||||||
|
|
||||||
|
if (getaddrinfo(domain.networkHost.c_str(), std::to_string(domain.httpPort).c_str(), &hints, &res) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reachable = false;
|
||||||
|
for (addrinfo* rp = res; rp; rp = rp->ai_next) {
|
||||||
|
int fd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
|
if (fd < 0) continue;
|
||||||
|
|
||||||
|
// Set non-blocking
|
||||||
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
|
||||||
|
int c = ::connect(fd, rp->ai_addr, rp->ai_addrlen);
|
||||||
|
if (c == 0) {
|
||||||
|
// Immediate success (rare for TCP)
|
||||||
|
reachable = true;
|
||||||
|
::close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == EINPROGRESS) {
|
||||||
|
// Wait for connect to complete or timeout
|
||||||
|
fd_set writefds;
|
||||||
|
FD_ZERO(&writefds);
|
||||||
|
FD_SET(fd, &writefds);
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = timeoutMs / 1000;
|
||||||
|
tv.tv_usec = (timeoutMs % 1000) * 1000;
|
||||||
|
|
||||||
|
int sel = select(fd + 1, nullptr, &writefds, nullptr, &tv);
|
||||||
|
if (sel > 0 && FD_ISSET(fd, &writefds)) {
|
||||||
|
// Check if connection succeeded
|
||||||
|
int error = 0;
|
||||||
|
socklen_t len = sizeof(error);
|
||||||
|
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0 && error == 0) {
|
||||||
|
reachable = true;
|
||||||
|
::close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res) freeaddrinfo(res);
|
||||||
|
return reachable;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user