using System.Net.Sockets; namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests; /// /// Lightweight TCP-connect probe used by E2E integration tests to detect whether a Docker /// fixture is reachable before attempting live work. Tests skip cleanly when this returns /// false; CI with fixtures available lets them run. /// public static class DockerFixtureAvailability { /// /// Attempts a TCP connect to :. Returns /// true if the connection is accepted within /// milliseconds; false on refusal, timeout, or DNS failure. /// /// The host to probe. /// The TCP port to connect to. /// Maximum time to wait in milliseconds; defaults to 500. public static bool IsReachable(string host, int port, int timeoutMs = 500) { try { // Force IPv4 — remote Docker host binds only on IPv4 (0.0.0.0). using var client = new TcpClient(AddressFamily.InterNetwork); var ipv4 = System.Net.Dns.GetHostAddresses(host) .FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork) ?? System.Net.IPAddress.Parse(host); var task = client.ConnectAsync(ipv4, port); return task.Wait(timeoutMs) && client.Connected; } catch { return false; } } /// /// Parses an HOST:PORT endpoint string and probes reachability. /// Returns true if the connection succeeds within /// milliseconds. Handles malformed strings gracefully by returning false. /// /// Endpoint in host:port format. /// Maximum time to wait in milliseconds; defaults to 500. public static bool IsReachable(string endpoint, int timeoutMs = 500) { try { var parts = endpoint.Split(':', 2); if (parts.Length != 2 || !int.TryParse(parts[1], out var port)) return false; return IsReachable(parts[0], port, timeoutMs); } catch { return false; } } }