mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-12-22 04:27:58 +01:00
Rework Proxy API
Instead of extending SocketFactory, the proxy support classes now implement ProxySocketConnection. This removes a lot of unnecessary code. Also re-enables proxy support, which was broken in previous versions because none of extended SocketFactories did override createSocket() (SMACK-683).
This commit is contained in:
parent
24365f0f1e
commit
7032688123
9 changed files with 104 additions and 266 deletions
|
@ -37,6 +37,12 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
|
|||
|
||||
private BOSHConfiguration(Builder builder) {
|
||||
super(builder);
|
||||
if (proxy != null) {
|
||||
if (proxy.getProxyType() != ProxyInfo.ProxyType.HTTP) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only HTTP proxies are support with BOSH connections");
|
||||
}
|
||||
}
|
||||
https = builder.https;
|
||||
if (builder.file.charAt(0) != '/') {
|
||||
file = '/' + builder.file;
|
||||
|
@ -46,7 +52,7 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
|
|||
}
|
||||
|
||||
public boolean isProxyEnabled() {
|
||||
return (proxy != null && proxy.getProxyType() != ProxyInfo.ProxyType.NONE);
|
||||
return proxy != null;
|
||||
}
|
||||
|
||||
public ProxyInfo getProxyInfo() {
|
||||
|
|
|
@ -125,14 +125,7 @@ public abstract class ConnectionConfiguration {
|
|||
port = builder.port;
|
||||
|
||||
proxy = builder.proxy;
|
||||
if (proxy != null) {
|
||||
if (builder.socketFactory != null) {
|
||||
throw new IllegalArgumentException("Can not use proxy together with custom socket factory");
|
||||
}
|
||||
socketFactory = proxy.getSocketFactory();
|
||||
} else {
|
||||
socketFactory = builder.socketFactory;
|
||||
}
|
||||
socketFactory = builder.socketFactory;
|
||||
|
||||
securityMode = builder.securityMode;
|
||||
keystoreType = builder.keystoreType;
|
||||
|
@ -300,6 +293,15 @@ public abstract class ConnectionConfiguration {
|
|||
return this.socketFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configured proxy information (if any).
|
||||
*
|
||||
* @return the configured proxy information or <code>null</code>.
|
||||
*/
|
||||
public ProxyInfo getProxyInfo() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration for TLS security modes that are available when making a connection
|
||||
* to the XMPP server.
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smack.proxy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* SocketFactory for direct connection
|
||||
*
|
||||
* @author Atul Aggarwal
|
||||
*/
|
||||
class DirectSocketFactory
|
||||
extends SocketFactory
|
||||
{
|
||||
|
||||
public DirectSocketFactory()
|
||||
{
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
Socket newSocket = new Socket(Proxy.NO_PROXY);
|
||||
newSocket.connect(new InetSocketAddress(host,port));
|
||||
return newSocket;
|
||||
}
|
||||
|
||||
public Socket createSocket(String host ,int port, InetAddress localHost,
|
||||
int localPort)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return new Socket(host,port,localHost,localPort);
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
Socket newSocket = new Socket(Proxy.NO_PROXY);
|
||||
newSocket.connect(new InetSocketAddress(host,port));
|
||||
return newSocket;
|
||||
}
|
||||
|
||||
public Socket createSocket( InetAddress address, int port,
|
||||
InetAddress localAddress, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
return new Socket(address,port,localAddress,localPort);
|
||||
}
|
||||
|
||||
}
|
|
@ -22,10 +22,8 @@ import java.io.InputStream;
|
|||
import java.io.StringReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||
|
||||
|
@ -33,56 +31,26 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Http Proxy Socket Factory which returns socket connected to Http Proxy
|
||||
* HTTP Proxy Socket Connection which connects the socket using a HTTP Proxy.
|
||||
*
|
||||
* @author Atul Aggarwal
|
||||
*/
|
||||
class HTTPProxySocketFactory
|
||||
extends SocketFactory
|
||||
{
|
||||
class HTTPProxySocketConnection implements ProxySocketConnection {
|
||||
|
||||
private ProxyInfo proxy;
|
||||
private final ProxyInfo proxy;
|
||||
|
||||
public HTTPProxySocketFactory(ProxyInfo proxy)
|
||||
HTTPProxySocketConnection(ProxyInfo proxy)
|
||||
{
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return httpProxifiedSocket(host, port);
|
||||
}
|
||||
|
||||
public Socket createSocket(String host ,int port, InetAddress localHost,
|
||||
int localPort)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return httpProxifiedSocket(host, port);
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
return httpProxifiedSocket(host.getHostAddress(), port);
|
||||
|
||||
}
|
||||
|
||||
public Socket createSocket( InetAddress address, int port,
|
||||
InetAddress localAddress, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
return httpProxifiedSocket(address.getHostAddress(), port);
|
||||
}
|
||||
|
||||
private Socket httpProxifiedSocket(String host, int port)
|
||||
throws IOException
|
||||
{
|
||||
@Override
|
||||
public void connect(Socket socket, InetAddress inetAddress, int port, int timeout)
|
||||
throws IOException {
|
||||
String proxyhost = proxy.getProxyAddress();
|
||||
int proxyPort = proxy.getProxyPort();
|
||||
@SuppressWarnings("resource")
|
||||
Socket socket = new Socket(proxyhost,proxyPort);
|
||||
String hostport = "CONNECT " + host + ":" + port;
|
||||
socket.connect(new InetSocketAddress(proxyhost, proxyPort));
|
||||
String hostport = "CONNECT " + inetAddress.getCanonicalHostName() + ":" + port;
|
||||
String proxyLine;
|
||||
String username = proxy.getProxyUsername();
|
||||
if (username == null)
|
||||
|
@ -164,8 +132,6 @@ class HTTPProxySocketFactory
|
|||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.HTTP);
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
private static final Pattern RESPONSE_PATTERN
|
|
@ -16,8 +16,6 @@
|
|||
*/
|
||||
package org.jivesoftware.smack.proxy;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* Class which stores proxy information such as proxy type, host, port,
|
||||
* authentication etc.
|
||||
|
@ -29,7 +27,6 @@ public class ProxyInfo
|
|||
{
|
||||
public static enum ProxyType
|
||||
{
|
||||
NONE,
|
||||
HTTP,
|
||||
SOCKS4,
|
||||
SOCKS5
|
||||
|
@ -40,6 +37,7 @@ public class ProxyInfo
|
|||
private String proxyUsername;
|
||||
private String proxyPassword;
|
||||
private ProxyType proxyType;
|
||||
private final ProxySocketConnection proxySocketConnection;
|
||||
|
||||
public ProxyInfo( ProxyType pType, String pHost, int pPort, String pUser,
|
||||
String pPass)
|
||||
|
@ -49,6 +47,19 @@ public class ProxyInfo
|
|||
this.proxyPort = pPort;
|
||||
this.proxyUsername = pUser;
|
||||
this.proxyPassword = pPass;
|
||||
switch (proxyType) {
|
||||
case HTTP:
|
||||
proxySocketConnection = new HTTPProxySocketConnection(this);
|
||||
break;
|
||||
case SOCKS4:
|
||||
proxySocketConnection = new Socks4ProxySocketConnection(this);
|
||||
break;
|
||||
case SOCKS5:
|
||||
proxySocketConnection = new Socks5ProxySocketConnection(this);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public static ProxyInfo forHttpProxy(String pHost, int pPort, String pUser,
|
||||
|
@ -69,16 +80,6 @@ public class ProxyInfo
|
|||
return new ProxyInfo(ProxyType.SOCKS5, pHost, pPort, pUser, pPass);
|
||||
}
|
||||
|
||||
public static ProxyInfo forNoProxy()
|
||||
{
|
||||
return new ProxyInfo(ProxyType.NONE, null, 0, null, null);
|
||||
}
|
||||
|
||||
public static ProxyInfo forDefaultProxy()
|
||||
{
|
||||
return new ProxyInfo(ProxyType.NONE, null, 0, null, null);
|
||||
}
|
||||
|
||||
public ProxyType getProxyType()
|
||||
{
|
||||
return proxyType;
|
||||
|
@ -104,27 +105,7 @@ public class ProxyInfo
|
|||
return proxyPassword;
|
||||
}
|
||||
|
||||
public SocketFactory getSocketFactory()
|
||||
{
|
||||
if(proxyType == ProxyType.NONE)
|
||||
{
|
||||
return new DirectSocketFactory();
|
||||
}
|
||||
else if(proxyType == ProxyType.HTTP)
|
||||
{
|
||||
return new HTTPProxySocketFactory(this);
|
||||
}
|
||||
else if(proxyType == ProxyType.SOCKS4)
|
||||
{
|
||||
return new Socks4ProxySocketFactory(this);
|
||||
}
|
||||
else if(proxyType == ProxyType.SOCKS5)
|
||||
{
|
||||
return new Socks5ProxySocketFactory(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public ProxySocketConnection getProxySocketConnection() {
|
||||
return proxySocketConnection;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015 Florian Schmaus.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
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)
|
||||
throws IOException;
|
||||
|
||||
}
|
|
@ -20,59 +20,25 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* Socket factory for socks4 proxy.
|
||||
*
|
||||
* @author Atul Aggarwal
|
||||
*/
|
||||
public class Socks4ProxySocketFactory
|
||||
extends SocketFactory
|
||||
{
|
||||
private ProxyInfo proxy;
|
||||
public class Socks4ProxySocketConnection implements ProxySocketConnection {
|
||||
private final ProxyInfo proxy;
|
||||
|
||||
public Socks4ProxySocketFactory(ProxyInfo proxy)
|
||||
Socks4ProxySocketConnection(ProxyInfo proxy)
|
||||
{
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return socks4ProxifiedSocket(host,port);
|
||||
|
||||
}
|
||||
|
||||
public Socket createSocket(String host ,int port, InetAddress localHost,
|
||||
int localPort)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return socks4ProxifiedSocket(host,port);
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
return socks4ProxifiedSocket(host.getHostAddress(),port);
|
||||
}
|
||||
|
||||
public Socket createSocket( InetAddress address, int port,
|
||||
InetAddress localAddress, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
return socks4ProxifiedSocket(address.getHostAddress(),port);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
private Socket socks4ProxifiedSocket(String host, int port)
|
||||
throws IOException
|
||||
{
|
||||
Socket socket = null;
|
||||
@Override
|
||||
public void connect(Socket socket, InetAddress inetAddress, int port, int timeout)
|
||||
throws IOException {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
String proxy_host = proxy.getProxyAddress();
|
||||
|
@ -81,7 +47,7 @@ public class Socks4ProxySocketFactory
|
|||
|
||||
try
|
||||
{
|
||||
socket=new Socket(proxy_host, proxy_port);
|
||||
socket.connect(new InetSocketAddress(proxy_host, proxy_port), timeout);
|
||||
in=socket.getInputStream();
|
||||
out=socket.getOutputStream();
|
||||
socket.setTcpNoDelay(true);
|
||||
|
@ -114,19 +80,10 @@ public class Socks4ProxySocketFactory
|
|||
buf[index++]=(byte)(port>>>8);
|
||||
buf[index++]=(byte)(port&0xff);
|
||||
|
||||
try
|
||||
byte[] byteAddress = inetAddress.getAddress();
|
||||
for (int i = 0; i < byteAddress.length; i++)
|
||||
{
|
||||
InetAddress addr=InetAddress.getByName(host);
|
||||
byte[] byteAddress = addr.getAddress();
|
||||
for (int i = 0; i < byteAddress.length; i++)
|
||||
{
|
||||
buf[index++]=byteAddress[i];
|
||||
}
|
||||
}
|
||||
catch(UnknownHostException uhe)
|
||||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
|
||||
uhe.toString(), uhe);
|
||||
buf[index++]=byteAddress[i];
|
||||
}
|
||||
|
||||
if(user!=null)
|
||||
|
@ -195,7 +152,6 @@ public class Socks4ProxySocketFactory
|
|||
}
|
||||
byte[] temp = new byte[2];
|
||||
in.read(temp, 0, 2);
|
||||
return socket;
|
||||
}
|
||||
catch(RuntimeException e)
|
||||
{
|
||||
|
@ -205,7 +161,7 @@ public class Socks4ProxySocketFactory
|
|||
{
|
||||
try
|
||||
{
|
||||
if(socket!=null)socket.close();
|
||||
socket.close();
|
||||
}
|
||||
catch(Exception eee)
|
||||
{
|
||||
|
@ -213,4 +169,5 @@ public class Socks4ProxySocketFactory
|
|||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -20,61 +20,25 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* Socket factory for Socks5 proxy.
|
||||
*
|
||||
* @author Atul Aggarwal
|
||||
*/
|
||||
public class Socks5ProxySocketFactory
|
||||
extends SocketFactory
|
||||
{
|
||||
private ProxyInfo proxy;
|
||||
public class Socks5ProxySocketConnection implements ProxySocketConnection {
|
||||
private final ProxyInfo proxy;
|
||||
|
||||
public Socks5ProxySocketFactory(ProxyInfo proxy)
|
||||
Socks5ProxySocketConnection(ProxyInfo proxy)
|
||||
{
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return socks5ProxifiedSocket(host,port);
|
||||
}
|
||||
|
||||
public Socket createSocket(String host ,int port, InetAddress localHost,
|
||||
int localPort)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
|
||||
return socks5ProxifiedSocket(host,port);
|
||||
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
return socks5ProxifiedSocket(host.getHostAddress(),port);
|
||||
|
||||
}
|
||||
|
||||
public Socket createSocket( InetAddress address, int port,
|
||||
InetAddress localAddress, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
return socks5ProxifiedSocket(address.getHostAddress(),port);
|
||||
|
||||
}
|
||||
|
||||
private Socket socks5ProxifiedSocket(String host, int port)
|
||||
throws IOException
|
||||
{
|
||||
Socket socket = null;
|
||||
@Override
|
||||
public void connect(Socket socket, InetAddress inetAddress, int port, int timeout)
|
||||
throws IOException {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
String proxy_host = proxy.getProxyAddress();
|
||||
|
@ -84,7 +48,7 @@ public class Socks5ProxySocketFactory
|
|||
|
||||
try
|
||||
{
|
||||
socket=new Socket(proxy_host, proxy_port);
|
||||
socket.connect(new InetSocketAddress(proxy_host, proxy_port), timeout);
|
||||
in=socket.getInputStream();
|
||||
out=socket.getOutputStream();
|
||||
|
||||
|
@ -247,7 +211,7 @@ public class Socks5ProxySocketFactory
|
|||
buf[index++]=1; // CONNECT
|
||||
buf[index++]=0;
|
||||
|
||||
byte[] hostb=host.getBytes();
|
||||
byte[] hostb= inetAddress.getCanonicalHostName().getBytes();
|
||||
int len=hostb.length;
|
||||
buf[index++]=3; // DOMAINNAME
|
||||
buf[index++]=(byte)(len);
|
||||
|
@ -327,8 +291,6 @@ public class Socks5ProxySocketFactory
|
|||
break;
|
||||
default:
|
||||
}
|
||||
return socket;
|
||||
|
||||
}
|
||||
catch(RuntimeException e)
|
||||
{
|
||||
|
@ -338,10 +300,7 @@ public class Socks5ProxySocketFactory
|
|||
{
|
||||
try
|
||||
{
|
||||
if(socket!=null)
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
socket.close();
|
||||
}
|
||||
catch(Exception eee)
|
||||
{
|
||||
|
@ -371,4 +330,5 @@ public class Socks5ProxySocketFactory
|
|||
s+=i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -68,6 +68,7 @@ import org.jivesoftware.smack.sm.predicates.Predicate;
|
|||
import org.jivesoftware.smack.sm.provider.ParseStreamManagement;
|
||||
import org.jivesoftware.smack.packet.Nonza;
|
||||
import org.jivesoftware.smack.packet.XMPPError;
|
||||
import org.jivesoftware.smack.proxy.ProxyInfo;
|
||||
import org.jivesoftware.smack.util.ArrayBlockingQueueWithShutdown;
|
||||
import org.jivesoftware.smack.util.Async;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
|
@ -531,6 +532,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
|||
private void connectUsingConfiguration() throws IOException, ConnectionException {
|
||||
List<HostAddress> failedAddresses = populateHostAddresses();
|
||||
SocketFactory socketFactory = config.getSocketFactory();
|
||||
ProxyInfo proxyInfo = config.getProxyInfo();
|
||||
int timeout = config.getConnectTimeout();
|
||||
if (socketFactory == null) {
|
||||
socketFactory = SocketFactory.getDefault();
|
||||
}
|
||||
|
@ -550,7 +553,12 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
|||
final String inetAddressAndPort = inetAddress + " at port " + port;
|
||||
LOGGER.finer("Trying to establish TCP connection to " + inetAddressAndPort);
|
||||
try {
|
||||
socket.connect(new InetSocketAddress(inetAddress, port), config.getConnectTimeout());
|
||||
if (proxyInfo == null) {
|
||||
socket.connect(new InetSocketAddress(inetAddress, port), timeout);
|
||||
}
|
||||
else {
|
||||
proxyInfo.getProxySocketConnection().connect(socket, inetAddress, port, timeout);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (inetAddresses.hasNext()) {
|
||||
continue innerloop;
|
||||
|
|
Loading…
Reference in a new issue