From c13b0b1fb9a4d9f984345e26c2d15e24203e8691 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 16 Jul 2015 13:46:30 +0200 Subject: Speed up things a bit, make WPAD guessing better --- .../search/desktop/DesktopProxySearchStrategy.java | 23 ++- .../proxy/search/wpad/WpadProxySearchStrategy.java | 187 ++++++++++----------- src/main/java/com/btr/proxy/util/PlatformUtil.java | 40 +++-- 3 files changed, 134 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java index 8a5a5d8..ca785f4 100644 --- a/src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java +++ b/src/main/java/com/btr/proxy/search/desktop/DesktopProxySearchStrategy.java @@ -8,11 +8,11 @@ import com.btr.proxy.search.desktop.kde.KdeProxySearchStrategy; import com.btr.proxy.search.desktop.osx.OsxProxySearchStrategy; import com.btr.proxy.search.desktop.win.WinProxySearchStrategy; import com.btr.proxy.util.Logger; -import com.btr.proxy.util.PlatformUtil; -import com.btr.proxy.util.ProxyException; import com.btr.proxy.util.Logger.LogLevel; +import com.btr.proxy.util.PlatformUtil; import com.btr.proxy.util.PlatformUtil.Desktop; import com.btr.proxy.util.PlatformUtil.Platform; +import com.btr.proxy.util.ProxyException; /***************************************************************************** * This search provider will try to find out on which desktop platform we @@ -22,6 +22,12 @@ import com.btr.proxy.util.PlatformUtil.Platform; ****************************************************************************/ public class DesktopProxySearchStrategy implements ProxySearchStrategy { + + private static final Object lock = new Object(); + + private static ProxySelector selector = null; + + private static long last = 0; /************************************************************************* * Gets the default ProxySelector for the current platform. @@ -30,8 +36,17 @@ public class DesktopProxySearchStrategy implements ProxySearchStrategy { ************************************************************************/ public ProxySelector getProxySelector() throws ProxyException { - ProxySearchStrategy strategy = findDesktopSpecificStrategy(); - return strategy == null? null : strategy.getProxySelector(); + long now = System.currentTimeMillis(); + synchronized (lock) { + if (last + 5000 < now) + return selector; + last = now; + ProxySearchStrategy strategy = findDesktopSpecificStrategy(); + if (strategy == null) + return null; + selector = strategy.getProxySelector(); + return selector; + } } /************************************************************************* diff --git a/src/main/java/com/btr/proxy/search/wpad/WpadProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/wpad/WpadProxySearchStrategy.java index cac3fe0..249a889 100644 --- a/src/main/java/com/btr/proxy/search/wpad/WpadProxySearchStrategy.java +++ b/src/main/java/com/btr/proxy/search/wpad/WpadProxySearchStrategy.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; +import java.net.InetAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.Socket; @@ -14,28 +15,32 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; +import java.net.UnknownHostException; import java.util.List; import java.util.Properties; import com.btr.proxy.search.ProxySearchStrategy; import com.btr.proxy.util.Logger; import com.btr.proxy.util.Logger.LogLevel; -import com.btr.proxy.util.ProxyException; import com.btr.proxy.util.ProxyUtil; - /***************************************************************************** * Uses automatic proxy script search (WPAD) to find an PAC file automatically. *

- * Note: at the moment only the DNS name guessing schema is implemented. - * All others are missing. - *

- * For more information about WPAD: - * Web_Proxy_Autodiscovery_Protocol - *

- * Outdated RFC draft: - * draft-ietf-wrec-wpad-01.txt + * Note: at the moment only the DNS name guessing schema is implemented. All + * others are missing. + *

+ *

+ * For more information about WPAD: Web_Proxy_Autodiscovery_Protocol + *

+ *

+ * Outdated RFC draft: draft-ietf-wrec-wpad-01.txt *

+ * * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 ****************************************************************************/ @@ -54,50 +59,33 @@ public class WpadProxySearchStrategy implements ProxySearchStrategy { * The location of the PAC file is determined automatically. * * @return a configured ProxySelector, null if none is found. - * @throws ProxyException on error. ************************************************************************/ - public ProxySelector getProxySelector() throws ProxyException { - try { - Logger.log(getClass(), LogLevel.TRACE, "Using WPAD to find a proxy"); + public ProxySelector getProxySelector() { + Logger.log(getClass(), LogLevel.TRACE, "Using WPAD to find a proxy"); - String pacScriptUrl = detectScriptUrlPerDHCP(); - if (pacScriptUrl == null) { - pacScriptUrl = detectScriptUrlPerDNS(); - } - if (pacScriptUrl == null) { - return null; - } - Logger.log(getClass(), LogLevel.TRACE, "PAC script url found: {0}", pacScriptUrl); - return ProxyUtil.buildPacSelectorForUrl(pacScriptUrl); - } catch (IOException e) { - Logger.log(getClass(), LogLevel.ERROR, "Error during WPAD search.", e); - throw new ProxyException(e); + String pacScriptUrl = detectScriptUrlPerDNS(); + if (pacScriptUrl == null) { + return null; } + Logger.log(getClass(), LogLevel.TRACE, "PAC script url found: {0}", pacScriptUrl); + return ProxyUtil.buildPacSelectorForUrl(pacScriptUrl); } /************************************************************************* * Loads the settings and stores them in a properties map. - * + * * @return the settings. ************************************************************************/ public Properties readSettings() { - try { - String pacScriptUrl = detectScriptUrlPerDHCP(); - if (pacScriptUrl == null) { - pacScriptUrl = detectScriptUrlPerDNS(); - } - if (pacScriptUrl == null) { - return null; - } - Properties result = new Properties(); - result.setProperty("url", pacScriptUrl); - return result; - } catch (IOException e) { - // Ignore and return empty properties. - return new Properties(); + String pacScriptUrl = detectScriptUrlPerDNS(); + if (pacScriptUrl == null) { + return null; } + Properties result = new Properties(); + result.setProperty("url", pacScriptUrl); + return result; } /************************************************************************* @@ -108,19 +96,34 @@ public class WpadProxySearchStrategy implements ProxySearchStrategy { * @return the URL, null if not found. ************************************************************************/ - private String detectScriptUrlPerDNS() throws IOException { - String result = null; - // String fqdn = InetAddress.getLocalHost().getCanonicalHostName(); + private String detectScriptUrlPerDNS() { // TODO: Java way of finding all search domains? Seems not trivial // Windows workaround could be running ipconfig /all and parsing... Logger.log(getClass(), LogLevel.TRACE, "Searching per DNS guessing."); - // Logger.log(getClass(), LogLevel.INFO, "fqdn: ", fqdn); + String ret; + int index; - FileReader fr = new FileReader("/etc/resolv.conf"); - BufferedReader br = new BufferedReader(fr); - ; + ret = tryUrl("http://wpad/wpad.dat"); + if (ret != null) + return ret; + + String fqdn = null; + try { + fqdn = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException e2) { + // No successfull, try other methods + } + if (fqdn != null && (index = fqdn.indexOf('.')) != -1) { + ret = tryUrl("http://wpad." + fqdn.substring(index + 1) + "/wpad.dat"); + if (ret != null) + return ret; + } + + BufferedReader br = null; String[] addresses = null; try { + FileReader fr = new FileReader("/etc/resolv.conf"); + br = new BufferedReader(fr); String input; while ((input = br.readLine()) != null) { if (input.startsWith("search")) { @@ -129,69 +132,60 @@ public class WpadProxySearchStrategy implements ProxySearchStrategy { break; } } + } catch (IOException e1) { + Logger.log(getClass(), LogLevel.DEBUG, "Could not read resolv.conf"); } finally { - br.close(); + try { + br.close(); + } catch (Exception e) { + } } if (addresses == null) { - addresses = new String[]{""}; + addresses = new String[] { "" }; } - String addr; for (int i = 0; i < addresses.length; ++i) { - String address = addresses[i].trim(); - if (address.length() < 1) + String address = addresses[i].trim().replaceAll("^\\.+", "").replaceAll("\\.+$", ""); + if (address.length() < 4) continue; do { - // Try to connect to URL - try { - if (address.length() != 0) - addr = "." + address; - else - addr = address; - URL lookupURL = new URL("http://wpad" + addr + "/wpad.dat"); - Logger.log(getClass(), LogLevel.DEBUG, "Trying url: {0}", lookupURL); - - HttpURLConnection con = (HttpURLConnection) lookupURL.openConnection(Proxy.NO_PROXY); - con.setConnectTimeout(1000); - con.setReadTimeout(2000); - con.setRequestMethod("HEAD"); - con.setInstanceFollowRedirects(true); - con.setRequestProperty("accept", "application/x-ns-proxy-autoconfig"); - if (con.getResponseCode() == 200) { - result = lookupURL.toString(); - return result; - } - con.disconnect(); - } catch (Exception e) { - Logger.log(getClass(), LogLevel.DEBUG, "Not available!"); - // Not a real error, try next address - } - if (address.length() == 0) { + ret = tryUrl("http://wpad." + address + "/wpad.dat"); + if (ret != null) + return ret; + // don't construct something like wpad.de.... + index = address.indexOf('.'); + if (index == -1 || index + 7 > address.length()) + break; + address = address.substring(index + 1); + if (address.indexOf('.') == -1) break; - } - int index = address.indexOf('.'); - if (index != -1 && index < address.length()) - address = address.substring(index + 1); - else - address = ""; - if (address.indexOf('.') == -1 || address.length() < 7) // don't construct something like wpad.de.... - address = ""; } while (true); } return null; } - /************************************************************************* - * Uses DHCP to find the script URL. - * - * @return the URL, null if not found. - ************************************************************************/ - - private String detectScriptUrlPerDHCP() { - Logger.log(getClass(), LogLevel.DEBUG, "Searching per DHCP not supported yet."); - // TODO Rossi 28.04.2009 Not implemented yet. + private String tryUrl(String url) { + try { + URL lookupURL = new URL(url); + Logger.log(getClass(), LogLevel.DEBUG, "Trying url: {0}", lookupURL); + + HttpURLConnection con = (HttpURLConnection) lookupURL.openConnection(Proxy.NO_PROXY); + con.setConnectTimeout(1500); + con.setReadTimeout(2500); + con.setRequestMethod("HEAD"); + con.setInstanceFollowRedirects(true); + con.setRequestProperty("accept", "application/x-ns-proxy-autoconfig"); + if (con.getResponseCode() == 200) { + String result = lookupURL.toString(); + return result; + } + con.disconnect(); + } catch (Exception e) { + Logger.log(getClass(), LogLevel.DEBUG, "Not available ({0})", e); + // Not a real error, try next address + } return null; } @@ -210,9 +204,6 @@ public class WpadProxySearchStrategy implements ProxySearchStrategy { Logger.log(WpadProxySearchStrategy.class, LogLevel.INFO, "proxyList contains: {0}", proxyList.toString()); } - } catch (ProxyException e) { - // TODO bjoern 28.10.2014 Auto-generated catch block - e.printStackTrace(); } catch (URISyntaxException e) { // TODO bjoern 28.10.2014 Auto-generated catch block e.printStackTrace(); diff --git a/src/main/java/com/btr/proxy/util/PlatformUtil.java b/src/main/java/com/btr/proxy/util/PlatformUtil.java index 39de5d2..52a25fd 100644 --- a/src/main/java/com/btr/proxy/util/PlatformUtil.java +++ b/src/main/java/com/btr/proxy/util/PlatformUtil.java @@ -14,33 +14,40 @@ public class PlatformUtil { public enum Desktop {WIN, KDE, GNOME, MAC_OS, OTHER} public enum Browser {IE, FIREFOX} + private static Platform platform = null; + private static Desktop desktop = null; + /************************************************************************* * Gets the platform we are currently running on. * @return a platform code. ************************************************************************/ - public static Platform getCurrentPlattform() { + public static synchronized Platform getCurrentPlattform() { + if (platform != null) + return platform; String osName = System.getProperty("os.name"); Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detecting platform. Name is: {0}", osName); if (osName.toLowerCase().contains("windows")) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Windows platform: {0}", osName); - return Platform.WIN; + platform = Platform.WIN; } if (osName.toLowerCase().contains("linux")) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Linux platform: {0}", osName); - return Platform.LINUX; + platform = Platform.LINUX; } if (osName.startsWith("Mac OS")) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Mac OS platform: {0}", osName); - return Platform.MAC_OS; + platform = Platform.MAC_OS; } if (osName.startsWith("SunOS")) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Solaris platform: {0}", osName); - return Platform.SOLARIS; + platform = Platform.SOLARIS; } - - return Platform.OTHER; + if (platform == null) { + platform = Platform.OTHER; + } + return platform; } /************************************************************************* @@ -64,16 +71,18 @@ public class PlatformUtil { * @return the desktop identifier. ************************************************************************/ - public static Desktop getCurrentDesktop() { + public static synchronized Desktop getCurrentDesktop() { + if (desktop != null) + return desktop; Platform platf = getCurrentPlattform(); if (platf == Platform.WIN) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Windows desktop"); - return Desktop.WIN; + desktop = Desktop.WIN; } if (platf == Platform.MAC_OS) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Mac OS desktop"); - return Desktop.MAC_OS; + desktop = Desktop.MAC_OS; } if (platf == Platform.LINUX @@ -82,15 +91,18 @@ public class PlatformUtil { if (isKDE()) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected KDE desktop"); - return Desktop.KDE; + desktop = Desktop.KDE; } if (isGnome()) { Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Gnome desktop"); - return Desktop.GNOME; + desktop = Desktop.GNOME; } } - Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Unknown desktop"); - return Desktop.OTHER; + if (desktop == null) { + Logger.log(PlatformUtil.class, LogLevel.TRACE, "Detected Unknown desktop"); + desktop = Desktop.OTHER; + } + return desktop; } /************************************************************************* -- cgit v1.2.3-55-g7522