IsPortActive checks to see if the given port on Docker IP is answering.
(port string)
| 17 | |
| 18 | // IsPortActive checks to see if the given port on Docker IP is answering. |
| 19 | func IsPortActive(port string) bool { |
| 20 | dialTimeout := 1 * time.Second |
| 21 | |
| 22 | dockerIP, err := dockerutil.GetDockerIP() |
| 23 | if err != nil { |
| 24 | util.Warning("Failed to get Docker IP address: %v", err) |
| 25 | return false |
| 26 | } |
| 27 | |
| 28 | // Skip port check for remote Docker hosts (non-local IPs) |
| 29 | // Remote IPs may cause timeouts and false positives |
| 30 | if parsedIP := net.ParseIP(dockerIP); parsedIP != nil && !parsedIP.IsLoopback() { |
| 31 | localIPs, _ := GetLocalIPs() |
| 32 | if !slices.Contains(localIPs, dockerIP) { |
| 33 | util.Verbose("Skipping port check for remote Docker host %s:%s", dockerIP, port) |
| 34 | return false |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | util.Verbose("Checking if port %s is active", port) |
| 39 | conn, err := net.DialTimeout("tcp", dockerIP+":"+port, dialTimeout) |
| 40 | |
| 41 | // If we were able to connect, something is listening on the port. |
| 42 | if err == nil { |
| 43 | _ = conn.Close() |
| 44 | return true |
| 45 | } |
| 46 | |
| 47 | // In WSL2 mirrored mode, when we test an unused port, we just get a timeout |
| 48 | // Assume that the port is available (not active) in that situation. |
| 49 | // This seems to be caused by https://github.com/microsoft/WSL/issues/10855 |
| 50 | // We don't have a way to know whether WSL2 in mirrored mode, but |
| 51 | // we use the longer timeout in WSL2 and assume that timeout is unoccupied. |
| 52 | if nodeps.IsWSL2() { |
| 53 | if err, ok := err.(net.Error); ok && err.Timeout() { |
| 54 | util.Debug("In WSL2 and port %s is probably not active; timeout", port) |
| 55 | return false |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | // If we get ECONNREFUSED the port is not active. |
| 60 | oe, ok := err.(*net.OpError) |
| 61 | if ok { |
| 62 | syscallErr, ok := oe.Err.(*os.SyscallError) |
| 63 | |
| 64 | // On Windows, WSAECONNREFUSED (10061) results instead of ECONNREFUSED. And golang doesn't seem to have it. |
| 65 | var WSAECONNREFUSED syscall.Errno = 10061 |
| 66 | |
| 67 | if ok && (syscallErr.Err == syscall.ECONNREFUSED || syscallErr.Err == WSAECONNREFUSED) { |
| 68 | util.Verbose("port %s shows connection refused so not active", port) |
| 69 | return false |
| 70 | } |
| 71 | } |
| 72 | // Otherwise, hmm, something else happened. It's not a fatal but can be reported. |
| 73 | util.Warning("Unable to properly check port status for %s:%s: err=%v", dockerIP, port, err) |
| 74 | return false |
| 75 | } |
| 76 |