package com.zillabyte.motherbrain.container; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import org.apache.log4j.Logger; import com.github.rholder.retry.RetryException; import com.zillabyte.motherbrain.utils.FileLockUtil; import com.zillabyte.motherbrain.utils.FileLockUtil.MultiLock; import com.zillabyte.motherbrain.utils.Utils; /** * Facilitates communication between the container and the host * @author sjarvie * */ public class TcpSocketHelper { public static final Logger _log = Utils.getLogger(TcpSocketHelper.class); public static int getRandomPort() { return 10000 + ((int)(Math.random() * 50000)); } /** * Allow the system to allocate a random lock for container to host communication. * @return */ public static ServerSocket getNextAvailableTcpSocket() throws ContainerException { MultiLock lock = null; try { lock = FileLockUtil.lock("/tmp/port_helper_lock"); return Utils.retry(3, new Callable<ServerSocket>() { @Override public ServerSocket call() throws Exception { int port = getRandomPort(); _log.info("attempting to use port: " + port); return new ServerSocket(port, 10, InetAddress.getByName("127.0.0.1")); // passing 0 = let system find next available port } }); } catch (IOException | InterruptedException | ExecutionException | RetryException e) { throw (ContainerException) new ContainerException(e).setUserMessage("Failed to initialize TCP socket.").adviseRetry(); } finally { try { if (lock != null) { lock.close(); } } catch (IOException e) { throw new RuntimeException(e); } } }; }