Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import eu.cloudnetservice.node.impl.service.InternalCloudServiceManager;
import eu.cloudnetservice.node.impl.service.defaults.factory.BaseLocalCloudServiceFactory;
import eu.cloudnetservice.node.impl.tick.DefaultTickLoop;
import eu.cloudnetservice.node.impl.util.NetworkUtil;
import eu.cloudnetservice.node.impl.version.ServiceVersionProvider;
import eu.cloudnetservice.node.service.CloudService;
import eu.cloudnetservice.node.service.CloudServiceManager;
Expand Down Expand Up @@ -95,4 +96,15 @@ public DockerizedLocalCloudServiceFactory(
public @NonNull String name() {
return this.dockerConfiguration.factoryName();
}

@Override
protected boolean isPortInUseAtOsLevel(@NonNull String hostAddress, int port) {
// only do OS-level port check if we can actually reach this address
// this handles the case where CloudNet runs in a container with an external address configured
if (!NetworkUtil.isBindableAddress(hostAddress)) {
return false;
}

return super.isPortInUseAtOsLevel(hostAddress, port);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,29 @@ protected int findFreeServicePort(

protected boolean isPortInUse(@NonNull CloudServiceManager manager, @NonNull String hostAddress, int port) {
// check if any local service has the port
if (this.isPortUsedByLocalService(manager, hostAddress, port)) {
return true;
}

// validate that the port is free at OS level
return this.isPortInUseAtOsLevel(hostAddress, port);
}

protected boolean isPortUsedByLocalService(
@NonNull CloudServiceManager manager,
@NonNull String hostAddress,
int port
) {
for (var cloudService : manager.localCloudServices()) {
var address = cloudService.serviceInfo().address();
if (address.host().equals(hostAddress) && address.port() == port) {
return true;
}
}
return false;
}

// validate that the port is free
protected boolean isPortInUseAtOsLevel(@NonNull String hostAddress, int port) {
return NetworkUtil.isInUse(hostAddress, port);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,35 @@ public static boolean checkAssignable(@NonNull HostAndPort hostAndPort) {
}
}

/**
* Checks if the given host address is bindable in the current network namespace.
*/
public static boolean isBindableAddress(@NonNull String hostAddress) {
// resolve the address to check against available addresses
String resolvedAddress;
try {
// try to parse as IP address first
var address = InetAddresses.forString(hostAddress);
// wildcard addresses are always bindable
if (address.isAnyLocalAddress()) {
return true;
}
resolvedAddress = extractHostAddress(address);
} catch (IllegalArgumentException exception) {
// not a raw IP address, try to resolve as hostname
try {
var address = InetAddress.getByName(hostAddress);
resolvedAddress = extractHostAddress(address);
} catch (UnknownHostException e) {
// cannot resolve hostname, not bindable
return false;
}
}

// check if the resolved address is available on this system
return availableIPAddresses().contains(resolvedAddress);
}

public static @Nullable HostAndPort parseAssignableHostAndPort(@NonNull String address, boolean withPort) {
// try to parse host and port from the given string
var hostAndPort = parseHostAndPort(address, withPort);
Expand Down
Loading