From 4c63cfafd7700c1c2089416acbe22a1e53196ecf Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Tue, 3 May 2016 09:59:20 +0200 Subject: [PATCH] Rework support for Proxy connections in order to improve support for Tor connections. This makes it possible to establish a connection to an .onion domain by manually setting host and port in the ConnectionConfiguration and configuring a Socks5Proxy pointing to a Tor node. Fixes SMACK-720. --- .../proxy/HTTPProxySocketConnection.java | 5 +- .../smack/proxy/ProxySocketConnection.java | 5 +- .../proxy/Socks4ProxySocketConnection.java | 3 +- .../proxy/Socks5ProxySocketConnection.java | 5 +- .../smack/tcp/XMPPTCPConnection.java | 77 +++++++++++-------- 5 files changed, 51 insertions(+), 44 deletions(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java index d818e6164..1e8932b31 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.net.HttpURLConnection; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; @@ -45,12 +44,12 @@ class HTTPProxySocketConnection implements ProxySocketConnection { } @Override - public void connect(Socket socket, InetAddress inetAddress, int port, int timeout) + public void connect(Socket socket, String host, int port, int timeout) throws IOException { String proxyhost = proxy.getProxyAddress(); int proxyPort = proxy.getProxyPort(); socket.connect(new InetSocketAddress(proxyhost, proxyPort)); - String hostport = "CONNECT " + inetAddress.getCanonicalHostName() + ":" + port; + String hostport = "CONNECT " + host + ":" + port; String proxyLine; String username = proxy.getProxyUsername(); if (username == null) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxySocketConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxySocketConnection.java index 75ce286df..ededc4522 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxySocketConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxySocketConnection.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015 Florian Schmaus. + * Copyright 2015-2016 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,11 @@ package org.jivesoftware.smack.proxy; import java.io.IOException; -import java.net.InetAddress; import java.net.Socket; public interface ProxySocketConnection { - public void connect(Socket socket, InetAddress inetAddress, int port, int timeout) + public void connect(Socket socket, String host, int port, int timeout) throws IOException; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks4ProxySocketConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks4ProxySocketConnection.java index cf0c354c9..40ef48215 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks4ProxySocketConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks4ProxySocketConnection.java @@ -37,7 +37,7 @@ public class Socks4ProxySocketConnection implements ProxySocketConnection { } @Override - public void connect(Socket socket, InetAddress inetAddress, int port, int timeout) + public void connect(Socket socket, String host, int port, int timeout) throws IOException { InputStream in = null; OutputStream out = null; @@ -80,6 +80,7 @@ public class Socks4ProxySocketConnection implements ProxySocketConnection { buf[index++]=(byte)(port>>>8); buf[index++]=(byte)(port&0xff); + InetAddress inetAddress = InetAddress.getByName(proxy_host); byte[] byteAddress = inetAddress.getAddress(); for (int i = 0; i < byteAddress.length; i++) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks5ProxySocketConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks5ProxySocketConnection.java index 85584ad2a..d7b71802e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks5ProxySocketConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/proxy/Socks5ProxySocketConnection.java @@ -19,7 +19,6 @@ package org.jivesoftware.smack.proxy; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; @@ -37,7 +36,7 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection { } @Override - public void connect(Socket socket, InetAddress inetAddress, int port, int timeout) + public void connect(Socket socket, String host, int port, int timeout) throws IOException { InputStream in = null; OutputStream out = null; @@ -211,7 +210,7 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection { buf[index++]=1; // CONNECT buf[index++]=0; - byte[] hostb= inetAddress.getCanonicalHostName().getBytes(); + byte[] hostb= host.getBytes(); int len=hostb.length; buf[index++]=3; // DOMAINNAME buf[index++]=(byte)(len); diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index b0ad9a506..e63cf9bac 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -554,48 +554,57 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { Iterator inetAddresses = null; String host = hostAddress.getFQDN(); int port = hostAddress.getPort(); - try { - inetAddresses = Arrays.asList(InetAddress.getAllByName(host)).iterator(); - if (!inetAddresses.hasNext()) { - // This should not happen - LOGGER.warning("InetAddress.getAllByName() returned empty result array."); - throw new UnknownHostException(host); - } - } - catch (UnknownHostException e) { - hostAddress.setException(e); - // TODO: Change to emptyIterator() once Smack's minimum Android SDK level is >= 19. - List emptyInetAddresses = Collections.emptyList(); - inetAddresses = emptyInetAddresses.iterator(); - continue; - } - innerloop: while (inetAddresses.hasNext()) { - final InetAddress inetAddress = inetAddresses.next(); - final String inetAddressAndPort = inetAddress + " at port " + port; - LOGGER.finer("Trying to establish TCP connection to " + inetAddressAndPort); + if (proxyInfo == null) { try { - if (proxyInfo == null) { - socket.connect(new InetSocketAddress(inetAddress, port), timeout); - } - else { - proxyInfo.getProxySocketConnection().connect(socket, inetAddress, port, timeout); - } - } catch (Exception e) { - hostAddress.setException(inetAddress, e); - if (inetAddresses.hasNext()) { - continue innerloop; - } - else { - break innerloop; + inetAddresses = Arrays.asList(InetAddress.getAllByName(host)).iterator(); + if (!inetAddresses.hasNext()) { + // This should not happen + LOGGER.warning("InetAddress.getAllByName() returned empty result array."); + throw new UnknownHostException(host); } + } catch (UnknownHostException e) { + hostAddress.setException(e); + // TODO: Change to emptyIterator() once Smack's minimum Android SDK level is >= 19. + List emptyInetAddresses = Collections.emptyList(); + inetAddresses = emptyInetAddresses.iterator(); + continue; } - LOGGER.finer("Established TCP connection to " + inetAddressAndPort); + innerloop: while (inetAddresses.hasNext()) { + final InetAddress inetAddress = inetAddresses.next(); + final String inetAddressAndPort = inetAddress + " at port " + port; + LOGGER.finer("Trying to establish TCP connection to " + inetAddressAndPort); + try { + socket.connect(new InetSocketAddress(inetAddress, port), timeout); + } catch (Exception e) { + hostAddress.setException(inetAddress, e); + if (inetAddresses.hasNext()) { + continue innerloop; + } else { + break innerloop; + } + } + LOGGER.finer("Established TCP connection to " + inetAddressAndPort); + // We found a host to connect to, return here + this.host = host; + this.port = port; + return; + } + failedAddresses.add(hostAddress); + } else { + final String hostAndPort = host + " at port " + port; + LOGGER.finer("Trying to establish TCP connection via Proxy to " + hostAndPort); + try { + proxyInfo.getProxySocketConnection().connect(socket, host, port, timeout); + } catch (IOException e) { + hostAddress.setException(e); + continue; + } + LOGGER.finer("Established TCP connection to " + hostAndPort); // We found a host to connect to, return here this.host = host; this.port = port; return; } - failedAddresses.add(hostAddress); } // There are no more host addresses to try // throw an exception and report all tried