diff --git a/G-Earth/src/main/java/gearth/protocol/HConnection.java b/G-Earth/src/main/java/gearth/protocol/HConnection.java index f4fa37f..c2e94a1 100644 --- a/G-Earth/src/main/java/gearth/protocol/HConnection.java +++ b/G-Earth/src/main/java/gearth/protocol/HConnection.java @@ -80,6 +80,8 @@ public class HConnection { } } catch (IOException e) { e.printStackTrace(); + setState(HState.ABORTING); + setState(HState.NOT_CONNECTED); } } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java index 5c68f08..092a420 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java @@ -7,6 +7,11 @@ import gearth.protocol.connection.proxy.ProxyProviderFactory; import gearth.protocol.connection.proxy.SocksConfiguration; import gearth.protocol.hostreplacer.hostsfile.HostReplacer; import gearth.protocol.hostreplacer.hostsfile.HostReplacerFactory; +import gearth.protocol.portchecker.PortChecker; +import gearth.protocol.portchecker.PortCheckerFactory; +import javafx.application.Platform; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; import java.io.IOException; import java.net.*; @@ -92,7 +97,19 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { for (int c = 0; c < potentialProxies.size(); c++) { HProxy potentialProxy = potentialProxies.get(c); - ServerSocket proxy_server = new ServerSocket(potentialProxy.getIntercept_port(), 10, InetAddress.getByName(potentialProxy.getIntercept_host())); + ServerSocket proxy_server; + try { + proxy_server = new ServerSocket(potentialProxy.getIntercept_port(), 10, InetAddress.getByName(potentialProxy.getIntercept_host())); + } catch (BindException e) { + PortChecker portChecker = PortCheckerFactory.getPortChecker(); + String processName = portChecker.getProcessUsingPort(potentialProxy.getIntercept_port()); + Platform.runLater(() -> { + Alert a = new Alert(Alert.AlertType.ERROR, "The port is in use by " + processName, + ButtonType.OK); + a.showAndWait(); + }); + throw new IOException(e); + } potentialProxy.initProxy(proxy_server); new Thread(() -> { diff --git a/G-Earth/src/main/java/gearth/protocol/portchecker/PortChecker.java b/G-Earth/src/main/java/gearth/protocol/portchecker/PortChecker.java new file mode 100644 index 0000000..3e34ba7 --- /dev/null +++ b/G-Earth/src/main/java/gearth/protocol/portchecker/PortChecker.java @@ -0,0 +1,38 @@ +package gearth.protocol.portchecker; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * This interface wraps the OS-dependant operation of checking if a specific port is used by any program. + * Some programs like McAfee TrueKey run on port 30000. This will hopefully save the user some time troubleshooting. + */ +public interface PortChecker { + /** + * @param port port to check + * @return process name or null if none + */ + String getProcessUsingPort(int port) throws IOException; + + /** Runs a command and reads the first line of output + * @param command Command to run + * @return {@link String} containing the output + * @throws IOException If an I/O error occurs + */ + default String getCommandOutput(String[] command) throws IOException { + try { + Runtime rt = Runtime.getRuntime(); + Process proc = rt.exec(command); + + BufferedReader stdInput = new BufferedReader(new + InputStreamReader(proc.getInputStream())); + + return stdInput.readLine(); + + } catch (IOException e) { + e.printStackTrace(); + throw e; + } + } +} diff --git a/G-Earth/src/main/java/gearth/protocol/portchecker/PortCheckerFactory.java b/G-Earth/src/main/java/gearth/protocol/portchecker/PortCheckerFactory.java new file mode 100644 index 0000000..ab9a533 --- /dev/null +++ b/G-Earth/src/main/java/gearth/protocol/portchecker/PortCheckerFactory.java @@ -0,0 +1,20 @@ +package gearth.protocol.portchecker; + +import gearth.misc.OSValidator; +import org.apache.commons.lang3.NotImplementedException; + +public final class PortCheckerFactory { + private PortCheckerFactory() {} + + public static PortChecker getPortChecker() { + if (OSValidator.isWindows()) { + return new WindowsPortChecker(); + } + + if (OSValidator.isUnix()) { + return new UnixPortChecker(); + } + + throw new NotImplementedException("macOS port checker not implemented yet"); + } +} diff --git a/G-Earth/src/main/java/gearth/protocol/portchecker/UnixPortChecker.java b/G-Earth/src/main/java/gearth/protocol/portchecker/UnixPortChecker.java new file mode 100644 index 0000000..c10cfe0 --- /dev/null +++ b/G-Earth/src/main/java/gearth/protocol/portchecker/UnixPortChecker.java @@ -0,0 +1,13 @@ +package gearth.protocol.portchecker; + +import java.io.IOException; + +public class UnixPortChecker implements PortChecker { + + @Override + public String getProcessUsingPort(int port) throws IOException { + String netstatOut = getCommandOutput(new String[] {"/bin/sh", "-c", " netstat -nlp | grep :" + port}); + int index = netstatOut.lastIndexOf("LISTEN "); + return netstatOut.substring(index + 12); + } +} diff --git a/G-Earth/src/main/java/gearth/protocol/portchecker/WindowsPortChecker.java b/G-Earth/src/main/java/gearth/protocol/portchecker/WindowsPortChecker.java new file mode 100644 index 0000000..771d946 --- /dev/null +++ b/G-Earth/src/main/java/gearth/protocol/portchecker/WindowsPortChecker.java @@ -0,0 +1,25 @@ +package gearth.protocol.portchecker; + +import java.io.IOException; + +public class WindowsPortChecker implements PortChecker{ + @Override + public String getProcessUsingPort(int port) throws IOException { + try { + String s = getCommandOutput(new String[] {"cmd", "/c", " netstat -ano | findstr LISTENING | findstr " + port}); + int index = s.lastIndexOf(" "); + String pid = s.substring(index); + + return getProcessNameFromPid(pid); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } + } + + private String getProcessNameFromPid(String pid) throws IOException { + String task = getCommandOutput(new String[] {"tasklist /fi \"pid eq " + pid + "\" /nh /fo:CSV"}); + int index = task.indexOf(','); + return task.substring(0, index); + } +}