mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 14:22:05 +01:00
Introduce util.InternetAddress
and use it where sensible. Also fixes a few unit tests along the way.
This commit is contained in:
parent
4334ca33ff
commit
b288768f77
11 changed files with 462 additions and 268 deletions
|
@ -0,0 +1,213 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2019 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.util;
|
||||||
|
|
||||||
|
import java.net.Inet4Address;
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import org.minidns.dnslabel.DnsLabel;
|
||||||
|
import org.minidns.dnsname.DnsName;
|
||||||
|
import org.minidns.dnsname.InvalidDnsNameException;
|
||||||
|
import org.minidns.util.InetAddressUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internet address, can be given as IP or as DNS name.
|
||||||
|
* <p>
|
||||||
|
* This type is meant for strings that hold an internet address. The original string used to construct this type is
|
||||||
|
* stored and returning in the {@link #toString()} method.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 4.4.0
|
||||||
|
*/
|
||||||
|
public abstract class InternetAddress implements CharSequence {
|
||||||
|
|
||||||
|
protected final String originalString;
|
||||||
|
|
||||||
|
protected InternetAddress(String originalString) {
|
||||||
|
this.originalString = Objects.requireNonNull(originalString, "The 'originalString' argument must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract InetAddress asInetAddress() throws UnknownHostException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return originalString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int length() {
|
||||||
|
return originalString.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char charAt(int index) {
|
||||||
|
return originalString.charAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence subSequence(int start, int end) {
|
||||||
|
return originalString.subSequence(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InternetAddress from(String address) {
|
||||||
|
final InternetAddress internetAddress;
|
||||||
|
if (InetAddressUtil.isIpV4Address(address)) {
|
||||||
|
internetAddress = new InternetAddress.Ipv4(address);
|
||||||
|
} else if (InetAddressUtil.isIpV6Address(address)) {
|
||||||
|
internetAddress = new InternetAddress.Ipv6(address);
|
||||||
|
} else if (address.contains(".")) {
|
||||||
|
InternetAddress domainNameInternetAddress;
|
||||||
|
try {
|
||||||
|
DnsName dnsName = DnsName.from(address);
|
||||||
|
domainNameInternetAddress = new InternetAddress.DomainName(address, dnsName);
|
||||||
|
} catch (InvalidDnsNameException e) {
|
||||||
|
domainNameInternetAddress = new InternetAddress.InvalidDomainName(address, e);
|
||||||
|
}
|
||||||
|
internetAddress = domainNameInternetAddress;
|
||||||
|
} else {
|
||||||
|
DnsLabel dnsLabel = DnsLabel.from(address);
|
||||||
|
internetAddress = new InternetAddress.DomainNameLabel(address, dnsLabel);
|
||||||
|
}
|
||||||
|
return internetAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InternetAddress from(InetAddress inetAddress) {
|
||||||
|
if (inetAddress instanceof Inet4Address) {
|
||||||
|
return new InternetAddress.Ipv4(inetAddress.getHostAddress(), (Inet4Address) inetAddress);
|
||||||
|
} else if (inetAddress instanceof Inet6Address) {
|
||||||
|
return new InternetAddress.Ipv6(inetAddress.getHostAddress(), (Inet6Address) inetAddress);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unknown type " + inetAddress.getClass() + " of " + inetAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class InetAddressInternetAddress extends InternetAddress {
|
||||||
|
private final InetAddress inetAddress;
|
||||||
|
|
||||||
|
protected InetAddressInternetAddress(String originalString, InetAddress inetAddress) {
|
||||||
|
super(originalString);
|
||||||
|
this.inetAddress = inetAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddress asInetAddress() {
|
||||||
|
return inetAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Ipv4 extends InetAddressInternetAddress {
|
||||||
|
|
||||||
|
private final Inet4Address inet4Address;
|
||||||
|
|
||||||
|
private Ipv4(String originalString) {
|
||||||
|
this(originalString, InetAddressUtil.ipv4From(originalString));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Ipv4(String originalString, Inet4Address inet4Address) {
|
||||||
|
super(originalString, inet4Address);
|
||||||
|
this.inet4Address = inet4Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inet4Address getInet4Address() {
|
||||||
|
return inet4Address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Ipv6 extends InetAddressInternetAddress {
|
||||||
|
|
||||||
|
private Inet6Address inet6Address;
|
||||||
|
|
||||||
|
private Ipv6(String originalString) {
|
||||||
|
this(originalString, InetAddressUtil.ipv6From(originalString));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Ipv6(String originalString, Inet6Address inet6Address) {
|
||||||
|
super(originalString, inet6Address);
|
||||||
|
this.inet6Address = inet6Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inet6Address getInet6Address() {
|
||||||
|
return inet6Address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class NonNumericInternetAddress extends InternetAddress {
|
||||||
|
private boolean attemptedToResolveInetAddress;
|
||||||
|
private InetAddress inetAddress;
|
||||||
|
|
||||||
|
protected NonNumericInternetAddress(String originalString) {
|
||||||
|
super(originalString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddress asInetAddress() throws UnknownHostException {
|
||||||
|
if (inetAddress != null || attemptedToResolveInetAddress) {
|
||||||
|
return inetAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
attemptedToResolveInetAddress = true;
|
||||||
|
inetAddress = InetAddress.getByName(originalString);
|
||||||
|
|
||||||
|
return inetAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class DomainName extends NonNumericInternetAddress {
|
||||||
|
|
||||||
|
private final DnsName dnsName;
|
||||||
|
|
||||||
|
private DomainName(String originalString, DnsName dnsName) {
|
||||||
|
super(originalString);
|
||||||
|
this.dnsName = dnsName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DnsName getDnsName() {
|
||||||
|
return dnsName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class DomainNameLabel extends NonNumericInternetAddress {
|
||||||
|
|
||||||
|
private final DnsLabel dnsLabel;
|
||||||
|
|
||||||
|
private DomainNameLabel(String originalString, DnsLabel dnsLabel) {
|
||||||
|
super(originalString);
|
||||||
|
this.dnsLabel = dnsLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DnsLabel getDnsLabel() {
|
||||||
|
return dnsLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class InvalidDomainName extends NonNumericInternetAddress {
|
||||||
|
|
||||||
|
private final InvalidDnsNameException invalidDnsNameException;
|
||||||
|
|
||||||
|
private InvalidDomainName(String originalString, InvalidDnsNameException invalidDnsNameException) {
|
||||||
|
super(originalString);
|
||||||
|
this.invalidDnsNameException = invalidDnsNameException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidDnsNameException getInvalidDnsNameException() {
|
||||||
|
return invalidDnsNameException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
package org.jivesoftware.smackx.bytestreams.socks5;
|
package org.jivesoftware.smackx.bytestreams.socks5;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -663,22 +664,16 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
|
||||||
EntityFullJid myJid = connection.getUser();
|
EntityFullJid myJid = connection.getUser();
|
||||||
|
|
||||||
for (Socks5Proxy socks5Server : Socks5Proxy.getRunningProxies()) {
|
for (Socks5Proxy socks5Server : Socks5Proxy.getRunningProxies()) {
|
||||||
List<String> addresses = socks5Server.getLocalAddresses();
|
List<InetAddress> addresses = socks5Server.getLocalAddresses();
|
||||||
if (addresses.isEmpty()) {
|
if (addresses.isEmpty()) {
|
||||||
// local address could not be determined
|
continue;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
final int port = socks5Server.getPort();
|
|
||||||
|
|
||||||
outerloop: for (String address : addresses) {
|
final int port = socks5Server.getPort();
|
||||||
|
for (InetAddress address : addresses) {
|
||||||
// Prevent loopback addresses from appearing as streamhost
|
// Prevent loopback addresses from appearing as streamhost
|
||||||
final String[] loopbackAddresses = { "127.0.0.1", "0:0:0:0:0:0:0:1", "::1" };
|
if (address.isLoopbackAddress()) {
|
||||||
for (String loopbackAddress : loopbackAddresses) {
|
continue;
|
||||||
// Use 'startsWith' here since IPv6 addresses may have scope ID,
|
|
||||||
// ie. the part after the '%' sign.
|
|
||||||
if (address.startsWith(loopbackAddress)) {
|
|
||||||
continue outerloop;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
streamHosts.add(new StreamHost(myJid, address, port));
|
streamHosts.add(new StreamHost(myJid, address, port));
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class Socks5Client {
|
||||||
|
|
||||||
// initialize socket
|
// initialize socket
|
||||||
Socket socket = new Socket();
|
Socket socket = new Socket();
|
||||||
SocketAddress socketAddress = new InetSocketAddress(streamHost.getAddress(),
|
SocketAddress socketAddress = new InetSocketAddress(streamHost.getAddress().asInetAddress(),
|
||||||
streamHost.getPort());
|
streamHost.getPort());
|
||||||
socket.connect(socketAddress);
|
socket.connect(socketAddress);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.InterfaceAddress;
|
||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
@ -52,7 +53,7 @@ import org.jivesoftware.smack.util.CloseableUtil;
|
||||||
* <p>
|
* <p>
|
||||||
* If your application is running on a machine with multiple network interfaces or if you want to
|
* If your application is running on a machine with multiple network interfaces or if you want to
|
||||||
* provide your public address in case you are behind a NAT router, invoke
|
* provide your public address in case you are behind a NAT router, invoke
|
||||||
* {@link #addLocalAddress(String)} or {@link #replaceLocalAddresses(Collection)} to modify the list of
|
* {@link #addLocalAddress(InetAddress)} or {@link #replaceLocalAddresses(Collection)} to modify the list of
|
||||||
* local network addresses used for outgoing SOCKS5 Bytestream requests.
|
* local network addresses used for outgoing SOCKS5 Bytestream requests.
|
||||||
* <p>
|
* <p>
|
||||||
* The local SOCKS5 proxy server refuses all connections except the ones that are explicitly allowed
|
* The local SOCKS5 proxy server refuses all connections except the ones that are explicitly allowed
|
||||||
|
@ -81,11 +82,17 @@ public final class Socks5Proxy {
|
||||||
|
|
||||||
private static boolean localSocks5ProxyEnabled = true;
|
private static boolean localSocks5ProxyEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default port of the local Socks5 Proxy. If this value is negative, the next ports will be tried
|
||||||
|
* until a unused is found.
|
||||||
|
*/
|
||||||
|
private static int DEFAULT_LOCAL_SOCKS5_PROXY_PORT = -7777;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The port of the local Socks5 Proxy. If this value is negative, the next ports will be tried
|
* The port of the local Socks5 Proxy. If this value is negative, the next ports will be tried
|
||||||
* until a unused is found.
|
* until a unused is found.
|
||||||
*/
|
*/
|
||||||
private static int localSocks5ProxyPort = -7777;
|
private int localSocks5ProxyPort = -7777;
|
||||||
|
|
||||||
/* reusable implementation of a SOCKS5 proxy server process */
|
/* reusable implementation of a SOCKS5 proxy server process */
|
||||||
private Socks5ServerProcess serverProcess;
|
private Socks5ServerProcess serverProcess;
|
||||||
|
@ -102,7 +109,7 @@ public final class Socks5Proxy {
|
||||||
/* list of digests connections should be stored */
|
/* list of digests connections should be stored */
|
||||||
private final List<String> allowedConnections = Collections.synchronizedList(new LinkedList<String>());
|
private final List<String> allowedConnections = Collections.synchronizedList(new LinkedList<String>());
|
||||||
|
|
||||||
private final Set<String> localAddresses = new LinkedHashSet<>(4);
|
private final Set<InetAddress> localAddresses = new LinkedHashSet<>(4);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor.
|
* Private constructor.
|
||||||
|
@ -116,21 +123,17 @@ public final class Socks5Proxy {
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
Set<String> localHostAddresses = new HashSet<>();
|
Set<InetAddress> localAddresses = new HashSet<>();
|
||||||
for (NetworkInterface networkInterface : Collections.list(networkInterfaces)) {
|
for (NetworkInterface networkInterface : Collections.list(networkInterfaces)) {
|
||||||
// We can't use NetworkInterface.getInterfaceAddresses here, which
|
List<InterfaceAddress> interfaceAddresses = networkInterface.getInterfaceAddresses();
|
||||||
// would return a List instead the deprecated Enumeration, because
|
for (InterfaceAddress interfaceAddress : interfaceAddresses) {
|
||||||
// it's Android API 9 and Smack currently uses 8. Change that when
|
localAddresses.add(interfaceAddress.getAddress());
|
||||||
// we raise Smack's minimum Android API.
|
|
||||||
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
|
|
||||||
for (InetAddress address : Collections.list(inetAddresses)) {
|
|
||||||
localHostAddresses.add(address.getHostAddress());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (localHostAddresses.isEmpty()) {
|
if (localAddresses.isEmpty()) {
|
||||||
throw new IllegalStateException("Could not determine any local host address");
|
throw new IllegalStateException("Could not determine any local internet address");
|
||||||
}
|
}
|
||||||
replaceLocalAddresses(localHostAddresses);
|
replaceLocalAddresses(localAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,12 +154,27 @@ public final class Socks5Proxy {
|
||||||
Socks5Proxy.localSocks5ProxyEnabled = localSocks5ProxyEnabled;
|
Socks5Proxy.localSocks5ProxyEnabled = localSocks5ProxyEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void checkLocalSocks5ProxyPortArgument(int port) {
|
||||||
|
if (Math.abs(port) > 65535) {
|
||||||
|
throw new IllegalArgumentException("Local SOCKS5 proxy port must be within (-65535,65535)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultLocalSocks5ProxyPort() {
|
||||||
|
return DEFAULT_LOCAL_SOCKS5_PROXY_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultLocalSocsk5ProxyPort(int defaultLocalSocks5ProxyPort) {
|
||||||
|
checkLocalSocks5ProxyPortArgument(defaultLocalSocks5ProxyPort);
|
||||||
|
DEFAULT_LOCAL_SOCKS5_PROXY_PORT = defaultLocalSocks5ProxyPort;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the port of the local Socks5 proxy. Default is 7777.
|
* Return the port of the local Socks5 proxy. Default is 7777.
|
||||||
*
|
*
|
||||||
* @return the port of the local Socks5 proxy
|
* @return the port of the local Socks5 proxy
|
||||||
*/
|
*/
|
||||||
public static int getLocalSocks5ProxyPort() {
|
public int getLocalSocks5ProxyPort() {
|
||||||
return localSocks5ProxyPort;
|
return localSocks5ProxyPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,11 +184,9 @@ public final class Socks5Proxy {
|
||||||
*
|
*
|
||||||
* @param localSocks5ProxyPort the port of the local Socks5 proxy to set
|
* @param localSocks5ProxyPort the port of the local Socks5 proxy to set
|
||||||
*/
|
*/
|
||||||
public static void setLocalSocks5ProxyPort(int localSocks5ProxyPort) {
|
public void setLocalSocks5ProxyPort(int localSocks5ProxyPort) {
|
||||||
if (Math.abs(localSocks5ProxyPort) > 65535) {
|
checkLocalSocks5ProxyPortArgument(localSocks5ProxyPort);
|
||||||
throw new IllegalArgumentException("localSocks5ProxyPort must be within (-65535,65535)");
|
this.localSocks5ProxyPort = localSocks5ProxyPort;
|
||||||
}
|
|
||||||
Socks5Proxy.localSocks5ProxyPort = localSocks5ProxyPort;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -269,7 +285,7 @@ public final class Socks5Proxy {
|
||||||
*
|
*
|
||||||
* @param address the local network address to add
|
* @param address the local network address to add
|
||||||
*/
|
*/
|
||||||
public void addLocalAddress(String address) {
|
public void addLocalAddress(InetAddress address) {
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -285,7 +301,7 @@ public final class Socks5Proxy {
|
||||||
* @param address the local network address to remove
|
* @param address the local network address to remove
|
||||||
* @return true if the address was removed.
|
* @return true if the address was removed.
|
||||||
*/
|
*/
|
||||||
public boolean removeLocalAddress(String address) {
|
public boolean removeLocalAddress(InetAddress address) {
|
||||||
synchronized (localAddresses) {
|
synchronized (localAddresses) {
|
||||||
return localAddresses.remove(address);
|
return localAddresses.remove(address);
|
||||||
}
|
}
|
||||||
|
@ -297,7 +313,7 @@ public final class Socks5Proxy {
|
||||||
*
|
*
|
||||||
* @return set of the local network addresses
|
* @return set of the local network addresses
|
||||||
*/
|
*/
|
||||||
public List<String> getLocalAddresses() {
|
public List<InetAddress> getLocalAddresses() {
|
||||||
synchronized (localAddresses) {
|
synchronized (localAddresses) {
|
||||||
return new LinkedList<>(localAddresses);
|
return new LinkedList<>(localAddresses);
|
||||||
}
|
}
|
||||||
|
@ -313,7 +329,7 @@ public final class Socks5Proxy {
|
||||||
*
|
*
|
||||||
* @param addresses the new list of local network addresses
|
* @param addresses the new list of local network addresses
|
||||||
*/
|
*/
|
||||||
public void replaceLocalAddresses(Collection<String> addresses) {
|
public void replaceLocalAddresses(Collection<? extends InetAddress> addresses) {
|
||||||
if (addresses == null) {
|
if (addresses == null) {
|
||||||
throw new IllegalArgumentException("list must not be null");
|
throw new IllegalArgumentException("list must not be null");
|
||||||
}
|
}
|
||||||
|
@ -482,12 +498,12 @@ public final class Socks5Proxy {
|
||||||
throw new SmackException.SmackMessageException("Connection is not allowed");
|
throw new SmackException.SmackMessageException("Connection is not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the connection before we send the return status.
|
||||||
|
Socks5Proxy.this.connectionMap.put(responseDigest, socket);
|
||||||
|
|
||||||
connectionRequest[1] = (byte) 0x00; // set return status to 0 (success)
|
connectionRequest[1] = (byte) 0x00; // set return status to 0 (success)
|
||||||
out.write(connectionRequest);
|
out.write(connectionRequest);
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
// store connection
|
|
||||||
Socks5Proxy.this.connectionMap.put(responseDigest, socket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,15 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.bytestreams.socks5.packet;
|
package org.jivesoftware.smackx.bytestreams.socks5.packet;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.packet.NamedElement;
|
import org.jivesoftware.smack.packet.NamedElement;
|
||||||
|
import org.jivesoftware.smack.util.InternetAddress;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
|
@ -117,7 +118,7 @@ public class Bytestream extends IQ {
|
||||||
* @param address The internet address of the stream host.
|
* @param address The internet address of the stream host.
|
||||||
* @return The added stream host.
|
* @return The added stream host.
|
||||||
*/
|
*/
|
||||||
public StreamHost addStreamHost(final Jid JID, final String address) {
|
public StreamHost addStreamHost(final Jid JID, String address) {
|
||||||
return addStreamHost(JID, address, 0);
|
return addStreamHost(JID, address, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ public class Bytestream extends IQ {
|
||||||
* @param port The port on which the remote host is seeking connections.
|
* @param port The port on which the remote host is seeking connections.
|
||||||
* @return The added stream host.
|
* @return The added stream host.
|
||||||
*/
|
*/
|
||||||
public StreamHost addStreamHost(final Jid JID, final String address, final int port) {
|
public StreamHost addStreamHost(final Jid JID, String address, final int port) {
|
||||||
StreamHost host = new StreamHost(JID, address, port);
|
StreamHost host = new StreamHost(JID, address, port);
|
||||||
addStreamHost(host);
|
addStreamHost(host);
|
||||||
|
|
||||||
|
@ -271,7 +272,7 @@ public class Bytestream extends IQ {
|
||||||
|
|
||||||
private final Jid jid;
|
private final Jid jid;
|
||||||
|
|
||||||
private final String address;
|
private final InternetAddress address;
|
||||||
|
|
||||||
private final int port;
|
private final int port;
|
||||||
|
|
||||||
|
@ -287,8 +288,23 @@ public class Bytestream extends IQ {
|
||||||
* @param port port of the stream host.
|
* @param port port of the stream host.
|
||||||
*/
|
*/
|
||||||
public StreamHost(final Jid jid, final String address, int port) {
|
public StreamHost(final Jid jid, final String address, int port) {
|
||||||
|
this(jid, InternetAddress.from(address), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamHost(Jid jid, InetAddress address, int port) {
|
||||||
|
this(jid, InternetAddress.from(address), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream Host constructor.
|
||||||
|
*
|
||||||
|
* @param jid The JID of the stream host.
|
||||||
|
* @param address The internet address of the stream host.
|
||||||
|
* @param port port of the stream host.
|
||||||
|
*/
|
||||||
|
public StreamHost(Jid jid, InternetAddress address, int port) {
|
||||||
this.jid = Objects.requireNonNull(jid, "StreamHost JID must not be null");
|
this.jid = Objects.requireNonNull(jid, "StreamHost JID must not be null");
|
||||||
this.address = StringUtils.requireNotNullNorEmpty(address, "StreamHost address must not be null");
|
this.address = Objects.requireNonNull(address);
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +322,7 @@ public class Bytestream extends IQ {
|
||||||
*
|
*
|
||||||
* @return Returns the internet address of the stream host.
|
* @return Returns the internet address of the stream host.
|
||||||
*/
|
*/
|
||||||
public String getAddress() {
|
public InternetAddress getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +344,7 @@ public class Bytestream extends IQ {
|
||||||
public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
||||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||||
xml.attribute("jid", getJID());
|
xml.attribute("jid", getJID());
|
||||||
xml.attribute("host", getAddress());
|
xml.attribute("host", address);
|
||||||
if (getPort() != 0) {
|
if (getPort() != 0) {
|
||||||
xml.attribute("port", Integer.toString(getPort()));
|
xml.attribute("port", Integer.toString(getPort()));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.jivesoftware.smackx.jingle.transports.jingle_s5b;
|
package org.jivesoftware.smackx.jingle.transports.jingle_s5b;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -162,7 +163,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
private UsedCandidate connectToTheirCandidate(JingleS5BTransportCandidate candidate)
|
private UsedCandidate connectToTheirCandidate(JingleS5BTransportCandidate candidate)
|
||||||
throws InterruptedException, TimeoutException, SmackException, XMPPException, IOException {
|
throws InterruptedException, TimeoutException, SmackException, XMPPException, IOException {
|
||||||
Bytestream.StreamHost streamHost = candidate.getStreamHost();
|
Bytestream.StreamHost streamHost = candidate.getStreamHost();
|
||||||
String address = streamHost.getAddress();
|
InetAddress address = streamHost.getAddress().asInetAddress();
|
||||||
Socks5Client socks5Client = new Socks5Client(streamHost, theirProposal.getDestinationAddress());
|
Socks5Client socks5Client = new Socks5Client(streamHost, theirProposal.getDestinationAddress());
|
||||||
Socket socket = socks5Client.getSocket(10 * 1000);
|
Socket socket = socks5Client.getSocket(10 * 1000);
|
||||||
LOGGER.log(Level.INFO, "Connected to their StreamHost " + address + " using dstAddr "
|
LOGGER.log(Level.INFO, "Connected to their StreamHost " + address + " using dstAddr "
|
||||||
|
@ -173,7 +174,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
private UsedCandidate connectToOurCandidate(JingleS5BTransportCandidate candidate)
|
private UsedCandidate connectToOurCandidate(JingleS5BTransportCandidate candidate)
|
||||||
throws InterruptedException, TimeoutException, SmackException, XMPPException, IOException {
|
throws InterruptedException, TimeoutException, SmackException, XMPPException, IOException {
|
||||||
Bytestream.StreamHost streamHost = candidate.getStreamHost();
|
Bytestream.StreamHost streamHost = candidate.getStreamHost();
|
||||||
String address = streamHost.getAddress();
|
InetAddress address = streamHost.getAddress().asInetAddress();
|
||||||
Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(
|
Socks5ClientForInitiator socks5Client = new Socks5ClientForInitiator(
|
||||||
streamHost, ourProposal.getDestinationAddress(), jingleSession.getConnection(),
|
streamHost, ourProposal.getDestinationAddress(), jingleSession.getConnection(),
|
||||||
ourProposal.getStreamId(), jingleSession.getRemote());
|
ourProposal.getStreamId(), jingleSession.getRemote());
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements;
|
package org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.InternetAddress;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
@ -40,14 +41,17 @@ public final class JingleS5BTransportCandidate extends JingleContentTransportCan
|
||||||
public static final String ATTR_TYPE = "type";
|
public static final String ATTR_TYPE = "type";
|
||||||
|
|
||||||
private final String cid;
|
private final String cid;
|
||||||
private final String host;
|
private final InternetAddress host;
|
||||||
private final Jid jid;
|
private final Jid jid;
|
||||||
private final int port;
|
private final int port;
|
||||||
private final int priority;
|
private final int priority;
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
|
||||||
public JingleS5BTransportCandidate(String candidateId, String host, Jid jid, int port, int priority, Type type) {
|
public JingleS5BTransportCandidate(String candidateId, String hostString, Jid jid, int port, int priority, Type type) {
|
||||||
|
this(candidateId, InternetAddress.from(hostString), jid, port, priority, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JingleS5BTransportCandidate(String candidateId, InternetAddress host, Jid jid, int port, int priority, Type type) {
|
||||||
Objects.requireNonNull(candidateId);
|
Objects.requireNonNull(candidateId);
|
||||||
Objects.requireNonNull(host);
|
Objects.requireNonNull(host);
|
||||||
Objects.requireNonNull(jid);
|
Objects.requireNonNull(jid);
|
||||||
|
@ -102,7 +106,7 @@ public final class JingleS5BTransportCandidate extends JingleContentTransportCan
|
||||||
return cid;
|
return cid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getHost() {
|
public InternetAddress getHost() {
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +153,7 @@ public final class JingleS5BTransportCandidate extends JingleContentTransportCan
|
||||||
|
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private String cid;
|
private String cid;
|
||||||
private String host;
|
private InternetAddress host;
|
||||||
private Jid jid;
|
private Jid jid;
|
||||||
private int port = -1;
|
private int port = -1;
|
||||||
private int priority = -1;
|
private int priority = -1;
|
||||||
|
@ -164,6 +168,11 @@ public final class JingleS5BTransportCandidate extends JingleContentTransportCan
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setHost(String host) {
|
public Builder setHost(String host) {
|
||||||
|
InternetAddress inetAddress = InternetAddress.from(host);
|
||||||
|
return setHost(inetAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setHost(InternetAddress host) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,10 +224,8 @@ public class InitiationListenerTest {
|
||||||
*
|
*
|
||||||
* @throws Exception should not happen
|
* @throws Exception should not happen
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedVariable")
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldInvokeAllRequestsListenerIfUserListenerExists() throws Exception {
|
public void shouldInvokeAllRequestsListenerIfUserListenerExists() throws Exception {
|
||||||
|
|
||||||
// add listener for all request
|
// add listener for all request
|
||||||
Socks5BytestreamListener allRequestsListener = mock(Socks5BytestreamListener.class);
|
Socks5BytestreamListener allRequestsListener = mock(Socks5BytestreamListener.class);
|
||||||
byteStreamManager.addIncomingBytestreamListener(allRequestsListener);
|
byteStreamManager.addIncomingBytestreamListener(allRequestsListener);
|
||||||
|
@ -241,15 +239,11 @@ public class InitiationListenerTest {
|
||||||
initiationListener.handleIQRequest(initBytestream);
|
initiationListener.handleIQRequest(initBytestream);
|
||||||
|
|
||||||
ArgumentCaptor<BytestreamRequest> byteStreamRequest = ArgumentCaptor.forClass(BytestreamRequest.class);
|
ArgumentCaptor<BytestreamRequest> byteStreamRequest = ArgumentCaptor.forClass(BytestreamRequest.class);
|
||||||
|
|
||||||
// assert all requests listener is called
|
// assert all requests listener is called
|
||||||
byteStreamRequest = ArgumentCaptor.forClass(BytestreamRequest.class);
|
|
||||||
verify(allRequestsListener, timeout(TIMEOUT)).incomingBytestreamRequest(byteStreamRequest.capture());
|
verify(allRequestsListener, timeout(TIMEOUT)).incomingBytestreamRequest(byteStreamRequest.capture());
|
||||||
|
|
||||||
// assert user request listener is not called
|
// assert user request listener is not called
|
||||||
verify(userRequestsListener, never()).incomingBytestreamRequest(byteStreamRequest.capture());
|
verify(userRequestsListener, never()).incomingBytestreamRequest(byteStreamRequest.capture());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,7 +29,9 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
@ -776,16 +778,24 @@ public class Socks5ByteStreamManagerTest {
|
||||||
streamHostUsedPacket.setSessionID(sessionID);
|
streamHostUsedPacket.setSessionID(sessionID);
|
||||||
streamHostUsedPacket.setUsedHost(initiatorJID); // local proxy used
|
streamHostUsedPacket.setUsedHost(initiatorJID); // local proxy used
|
||||||
|
|
||||||
|
final String secondStreamHostIp = "192.0.0.1";
|
||||||
// return used stream host info as response to the bytestream initiation
|
// return used stream host info as response to the bytestream initiation
|
||||||
protocol.addResponse(streamHostUsedPacket, new Verification<Bytestream, Bytestream>() {
|
protocol.addResponse(streamHostUsedPacket, new Verification<Bytestream, Bytestream>() {
|
||||||
@Override
|
@Override
|
||||||
public void verify(Bytestream request, Bytestream response) {
|
public void verify(Bytestream request, Bytestream response) {
|
||||||
assertEquals(response.getSessionID(), request.getSessionID());
|
assertEquals(response.getSessionID(), request.getSessionID());
|
||||||
StreamHost streamHost1 = request.getStreamHosts().get(0);
|
|
||||||
|
List<StreamHost> streamHosts = request.getStreamHosts();
|
||||||
|
|
||||||
|
StreamHost streamHost1 = streamHosts.get(0);
|
||||||
assertEquals(response.getUsedHost().getJID(), streamHost1.getJID());
|
assertEquals(response.getUsedHost().getJID(), streamHost1.getJID());
|
||||||
StreamHost streamHost2 = request.getStreamHosts().get(request.getStreamHosts().size() - 1);
|
|
||||||
|
// Get the last stream host. Note that there may be multiple, but since this unit test added
|
||||||
|
// secondStreamHostIp as last, it should also be the last entry since the API contract assures that
|
||||||
|
// the order is preserved.
|
||||||
|
StreamHost streamHost2 = streamHosts.get(streamHosts.size() - 1);
|
||||||
assertEquals(response.getUsedHost().getJID(), streamHost2.getJID());
|
assertEquals(response.getUsedHost().getJID(), streamHost2.getJID());
|
||||||
assertEquals("localAddress", streamHost2.getAddress());
|
assertEquals(secondStreamHostIp, streamHost2.getAddress().toString());
|
||||||
}
|
}
|
||||||
}, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
|
}, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
|
||||||
|
|
||||||
|
@ -798,10 +808,10 @@ public class Socks5ByteStreamManagerTest {
|
||||||
socks5Proxy.getLocalAddresses().get(0),
|
socks5Proxy.getLocalAddresses().get(0),
|
||||||
socks5Proxy.getPort());
|
socks5Proxy.getPort());
|
||||||
Socks5Client socks5Client = new Socks5Client(streamHost, digest);
|
Socks5Client socks5Client = new Socks5Client(streamHost, digest);
|
||||||
InputStream inputStream = socks5Client.getSocket(2000).getInputStream();
|
InputStream inputStream = socks5Client.getSocket(10000).getInputStream();
|
||||||
|
|
||||||
// add another network address before establishing SOCKS5 Bytestream
|
// add another network address before establishing SOCKS5 Bytestream
|
||||||
socks5Proxy.addLocalAddress("localAddress");
|
socks5Proxy.addLocalAddress(InetAddress.getByName(secondStreamHostIp));
|
||||||
|
|
||||||
// finally call the method that should be tested
|
// finally call the method that should be tested
|
||||||
OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
|
OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
|
||||||
|
|
|
@ -35,7 +35,6 @@ import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,12 +47,10 @@ public class Socks5ProxyTest {
|
||||||
private static final String loopbackAddress = InetAddress.getLoopbackAddress().getHostAddress();
|
private static final String loopbackAddress = InetAddress.getLoopbackAddress().getHostAddress();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SOCKS5 proxy should be a singleton used by all XMPP connections.
|
* The SOCKS5 proxy should be a quasi singleton used by all XMPP connections.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldBeASingleton() {
|
public void shouldBeAQuasiSingleton() {
|
||||||
Socks5Proxy.setLocalSocks5ProxyEnabled(false);
|
|
||||||
|
|
||||||
Socks5Proxy proxy1 = Socks5Proxy.getSocks5Proxy();
|
Socks5Proxy proxy1 = Socks5Proxy.getSocks5Proxy();
|
||||||
Socks5Proxy proxy2 = Socks5Proxy.getSocks5Proxy();
|
Socks5Proxy proxy2 = Socks5Proxy.getSocks5Proxy();
|
||||||
|
|
||||||
|
@ -62,16 +59,6 @@ public class Socks5ProxyTest {
|
||||||
assertSame(proxy1, proxy2);
|
assertSame(proxy1, proxy2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The SOCKS5 proxy should not be started if disabled by configuration.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void shouldNotBeRunningIfDisabled() {
|
|
||||||
Socks5Proxy.setLocalSocks5ProxyEnabled(false);
|
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
assertFalse(proxy.isRunning());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SOCKS5 proxy should use a free port above the one configured.
|
* The SOCKS5 proxy should use a free port above the one configured.
|
||||||
*
|
*
|
||||||
|
@ -79,44 +66,45 @@ public class Socks5ProxyTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldUseFreePortOnNegativeValues() throws Exception {
|
public void shouldUseFreePortOnNegativeValues() throws Exception {
|
||||||
Socks5Proxy.setLocalSocks5ProxyEnabled(false);
|
Socks5Proxy proxy = new Socks5Proxy();
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
assertFalse(proxy.isRunning());
|
assertFalse(proxy.isRunning());
|
||||||
|
|
||||||
ServerSocket serverSocket = new ServerSocket(0);
|
try (ServerSocket serverSocket = new ServerSocket(0)) {
|
||||||
Socks5Proxy.setLocalSocks5ProxyPort(-serverSocket.getLocalPort());
|
proxy.setLocalSocks5ProxyPort(-serverSocket.getLocalPort());
|
||||||
|
|
||||||
proxy.start();
|
proxy.start();
|
||||||
|
|
||||||
assertTrue(proxy.isRunning());
|
assertTrue(proxy.isRunning());
|
||||||
|
|
||||||
serverSocket.close();
|
|
||||||
|
|
||||||
assertTrue(proxy.getPort() > serverSocket.getLocalPort());
|
assertTrue(proxy.getPort() > serverSocket.getLocalPort());
|
||||||
|
} finally {
|
||||||
|
proxy.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When inserting new network addresses to the proxy the order should remain in the order they
|
* When inserting new network addresses to the proxy the order should remain in the order they
|
||||||
* were inserted.
|
* were inserted.
|
||||||
|
*
|
||||||
|
* @throws UnknownHostException
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldPreserveAddressOrderOnInsertions() {
|
public void shouldPreserveAddressOrderOnInsertions() throws UnknownHostException {
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
||||||
|
|
||||||
LinkedHashSet<String> addresses = new LinkedHashSet<>(proxy.getLocalAddresses());
|
LinkedHashSet<InetAddress> addresses = new LinkedHashSet<>(proxy.getLocalAddresses());
|
||||||
|
|
||||||
for (int i = 1 ; i <= 3; i++) {
|
for (int i = 1 ; i <= 3; i++) {
|
||||||
addresses.add(Integer.toString(i));
|
addresses.add(InetAddress.getByName(Integer.toString(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String address : addresses) {
|
for (InetAddress address : addresses) {
|
||||||
proxy.addLocalAddress(address);
|
proxy.addLocalAddress(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> localAddresses = proxy.getLocalAddresses();
|
List<InetAddress> localAddresses = proxy.getLocalAddresses();
|
||||||
|
|
||||||
Iterator<String> iterator = addresses.iterator();
|
Iterator<InetAddress> iterator = addresses.iterator();
|
||||||
for (int i = 0; i < addresses.size(); i++) {
|
for (int i = 0; i < addresses.size(); i++) {
|
||||||
assertEquals(iterator.next(), localAddresses.get(i));
|
assertEquals(iterator.next(), localAddresses.get(i));
|
||||||
}
|
}
|
||||||
|
@ -125,44 +113,25 @@ public class Socks5ProxyTest {
|
||||||
/**
|
/**
|
||||||
* When replacing network addresses of the proxy the order should remain in the order if the
|
* When replacing network addresses of the proxy the order should remain in the order if the
|
||||||
* given list.
|
* given list.
|
||||||
|
*
|
||||||
|
* @throws UnknownHostException
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldPreserveAddressOrderOnReplace() {
|
public void shouldPreserveAddressOrderOnReplace() throws UnknownHostException {
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
||||||
List<String> addresses = new ArrayList<>(proxy.getLocalAddresses());
|
List<InetAddress> addresses = new ArrayList<>(proxy.getLocalAddresses());
|
||||||
addresses.add("1");
|
addresses.add(InetAddress.getByName("1"));
|
||||||
addresses.add("2");
|
addresses.add(InetAddress.getByName("2"));
|
||||||
addresses.add("3");
|
addresses.add(InetAddress.getByName("3"));
|
||||||
|
|
||||||
proxy.replaceLocalAddresses(addresses);
|
proxy.replaceLocalAddresses(addresses);
|
||||||
|
|
||||||
List<String> localAddresses = proxy.getLocalAddresses();
|
List<InetAddress> localAddresses = proxy.getLocalAddresses();
|
||||||
for (int i = 0; i < addresses.size(); i++) {
|
for (int i = 0; i < addresses.size(); i++) {
|
||||||
assertEquals(addresses.get(i), localAddresses.get(i));
|
assertEquals(addresses.get(i), localAddresses.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserting the same address multiple times should not cause the proxy to return this address
|
|
||||||
* multiple times.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void shouldNotReturnMultipleSameAddress() {
|
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
|
|
||||||
proxy.addLocalAddress("same");
|
|
||||||
proxy.addLocalAddress("same");
|
|
||||||
proxy.addLocalAddress("same");
|
|
||||||
|
|
||||||
int sameCount = 0;
|
|
||||||
for (String localAddress : proxy.getLocalAddresses()) {
|
|
||||||
if ("same".equals(localAddress)) {
|
|
||||||
sameCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertEquals(1, sameCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the SOCKS5 proxy accepts a connection that is not a SOCKS5 connection it should close the
|
* If the SOCKS5 proxy accepts a connection that is not a SOCKS5 connection it should close the
|
||||||
* corresponding socket.
|
* corresponding socket.
|
||||||
|
@ -171,13 +140,10 @@ public class Socks5ProxyTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldCloseSocketIfNoSocks5Request() throws Exception {
|
public void shouldCloseSocketIfNoSocks5Request() throws Exception {
|
||||||
Socks5Proxy.setLocalSocks5ProxyPort(7890);
|
Socks5Proxy proxy = new Socks5Proxy();
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
proxy.start();
|
proxy.start();
|
||||||
|
|
||||||
@SuppressWarnings("resource")
|
try (Socket socket = new Socket(loopbackAddress, proxy.getPort())) {
|
||||||
Socket socket = new Socket(loopbackAddress, proxy.getPort());
|
|
||||||
|
|
||||||
OutputStream out = socket.getOutputStream();
|
OutputStream out = socket.getOutputStream();
|
||||||
out.write(new byte[] { 1, 2, 3 });
|
out.write(new byte[] { 1, 2, 3 });
|
||||||
|
|
||||||
|
@ -189,9 +155,9 @@ public class Socks5ProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(-1, res);
|
assertEquals(-1, res);
|
||||||
|
} finally {
|
||||||
proxy.stop();
|
proxy.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,13 +168,10 @@ public class Socks5ProxyTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldRespondWithErrorIfNoSupportedAuthenticationMethod() throws Exception {
|
public void shouldRespondWithErrorIfNoSupportedAuthenticationMethod() throws Exception {
|
||||||
Socks5Proxy.setLocalSocks5ProxyPort(7890);
|
Socks5Proxy proxy = new Socks5Proxy();
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
proxy.start();
|
proxy.start();
|
||||||
|
|
||||||
@SuppressWarnings("resource")
|
try (Socket socket = new Socket(loopbackAddress, proxy.getPort())) {
|
||||||
Socket socket = new Socket(loopbackAddress, proxy.getPort());
|
|
||||||
|
|
||||||
OutputStream out = socket.getOutputStream();
|
OutputStream out = socket.getOutputStream();
|
||||||
|
|
||||||
// request username/password-authentication
|
// request username/password-authentication
|
||||||
|
@ -220,9 +183,9 @@ public class Socks5ProxyTest {
|
||||||
assertEquals((byte) 0xFF, (byte) in.read());
|
assertEquals((byte) 0xFF, (byte) in.read());
|
||||||
|
|
||||||
assertEquals(-1, in.read());
|
assertEquals(-1, in.read());
|
||||||
|
} finally {
|
||||||
proxy.stop();
|
proxy.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,13 +196,10 @@ public class Socks5ProxyTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldRespondWithErrorIfConnectionIsNotAllowed() throws Exception {
|
public void shouldRespondWithErrorIfConnectionIsNotAllowed() throws Exception {
|
||||||
Socks5Proxy.setLocalSocks5ProxyPort(7890);
|
Socks5Proxy proxy = new Socks5Proxy();
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
proxy.start();
|
proxy.start();
|
||||||
|
|
||||||
@SuppressWarnings("resource")
|
try (Socket socket = new Socket(loopbackAddress, proxy.getPort())) {
|
||||||
Socket socket = new Socket(loopbackAddress, proxy.getPort());
|
|
||||||
|
|
||||||
OutputStream out = socket.getOutputStream();
|
OutputStream out = socket.getOutputStream();
|
||||||
out.write(new byte[] { (byte) 0x05, (byte) 0x01, (byte) 0x00 });
|
out.write(new byte[] { (byte) 0x05, (byte) 0x01, (byte) 0x00 });
|
||||||
|
|
||||||
|
@ -249,8 +209,8 @@ public class Socks5ProxyTest {
|
||||||
assertEquals((byte) 0x00, (byte) in.read());
|
assertEquals((byte) 0x00, (byte) in.read());
|
||||||
|
|
||||||
// send valid SOCKS5 message
|
// send valid SOCKS5 message
|
||||||
out.write(new byte[] { (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01,
|
out.write(new byte[] { (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0xAA,
|
||||||
(byte) 0xAA, (byte) 0x00, (byte) 0x00 });
|
(byte) 0x00, (byte) 0x00 });
|
||||||
|
|
||||||
// verify error message
|
// verify error message
|
||||||
assertEquals((byte) 0x05, (byte) in.read());
|
assertEquals((byte) 0x05, (byte) in.read());
|
||||||
|
@ -263,9 +223,9 @@ public class Socks5ProxyTest {
|
||||||
assertEquals((byte) 0x00, (byte) in.read());
|
assertEquals((byte) 0x00, (byte) in.read());
|
||||||
|
|
||||||
assertEquals(-1, in.read());
|
assertEquals(-1, in.read());
|
||||||
|
} finally {
|
||||||
proxy.stop();
|
proxy.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,10 +235,10 @@ public class Socks5ProxyTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void shouldSuccessfullyEstablishConnection() throws Exception {
|
public void shouldSuccessfullyEstablishConnection() throws Exception {
|
||||||
Socks5Proxy.setLocalSocks5ProxyPort(7890);
|
Socks5Proxy proxy = new Socks5Proxy();
|
||||||
Socks5Proxy proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
proxy.start();
|
proxy.start();
|
||||||
|
|
||||||
|
try {
|
||||||
assertTrue(proxy.isRunning());
|
assertTrue(proxy.isRunning());
|
||||||
String digest = new String(new byte[] { (byte) 0xAA }, StandardCharsets.UTF_8);
|
String digest = new String(new byte[] { (byte) 0xAA }, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
@ -297,8 +257,8 @@ public class Socks5ProxyTest {
|
||||||
assertEquals((byte) 0x00, (byte) in.read());
|
assertEquals((byte) 0x00, (byte) in.read());
|
||||||
|
|
||||||
// send valid SOCKS5 message
|
// send valid SOCKS5 message
|
||||||
out.write(new byte[] { (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01,
|
out.write(new byte[] { (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0xAA,
|
||||||
(byte) 0xAA, (byte) 0x00, (byte) 0x00 });
|
(byte) 0x00, (byte) 0x00 });
|
||||||
|
|
||||||
// verify response
|
// verify response
|
||||||
assertEquals((byte) 0x05, (byte) in.read());
|
assertEquals((byte) 0x05, (byte) in.read());
|
||||||
|
@ -310,10 +270,9 @@ public class Socks5ProxyTest {
|
||||||
assertEquals((byte) 0x00, (byte) in.read());
|
assertEquals((byte) 0x00, (byte) in.read());
|
||||||
assertEquals((byte) 0x00, (byte) in.read());
|
assertEquals((byte) 0x00, (byte) in.read());
|
||||||
|
|
||||||
Thread.sleep(200);
|
|
||||||
|
|
||||||
Socket remoteSocket = proxy.getSocket(digest);
|
Socket remoteSocket = proxy.getSocket(digest);
|
||||||
|
|
||||||
|
try {
|
||||||
// remove digest
|
// remove digest
|
||||||
proxy.removeTransfer(digest);
|
proxy.removeTransfer(digest);
|
||||||
|
|
||||||
|
@ -326,34 +285,13 @@ public class Socks5ProxyTest {
|
||||||
for (int i = 0; i < data.length; i++) {
|
for (int i = 0; i < data.length; i++) {
|
||||||
assertEquals(data[i], in.read());
|
assertEquals(data[i], in.read());
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
remoteSocket.close();
|
remoteSocket.close();
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(-1, in.read());
|
assertEquals(-1, in.read());
|
||||||
|
} finally {
|
||||||
proxy.stop();
|
proxy.stop();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset SOCKS5 proxy settings.
|
|
||||||
*/
|
|
||||||
@After
|
|
||||||
public void cleanup() {
|
|
||||||
Socks5Proxy.setLocalSocks5ProxyEnabled(true);
|
|
||||||
Socks5Proxy.setLocalSocks5ProxyPort(7777);
|
|
||||||
Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
|
|
||||||
try {
|
|
||||||
String address = InetAddress.getLocalHost().getHostAddress();
|
|
||||||
List<String> addresses = new ArrayList<>();
|
|
||||||
addresses.add(address);
|
|
||||||
socks5Proxy.replaceLocalAddresses(addresses);
|
|
||||||
}
|
}
|
||||||
catch (UnknownHostException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
socks5Proxy.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ import static junit.framework.TestCase.assertNotNull;
|
||||||
import static junit.framework.TestCase.assertNull;
|
import static junit.framework.TestCase.assertNull;
|
||||||
import static junit.framework.TestCase.assertTrue;
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
||||||
import org.jivesoftware.smack.test.util.TestUtils;
|
import org.jivesoftware.smack.test.util.TestUtils;
|
||||||
|
|
||||||
|
@ -89,7 +91,7 @@ public class JingleS5BTransportTest extends SmackTestSuite {
|
||||||
assertNotNull(candidate1.getStreamHost());
|
assertNotNull(candidate1.getStreamHost());
|
||||||
assertEquals(JingleS5BTransportCandidate.Type.direct.getWeight(), candidate1.getType().getWeight());
|
assertEquals(JingleS5BTransportCandidate.Type.direct.getWeight(), candidate1.getType().getWeight());
|
||||||
assertEquals("hft54dqy", candidate1.getCandidateId());
|
assertEquals("hft54dqy", candidate1.getCandidateId());
|
||||||
assertEquals("192.168.4.1", candidate1.getHost());
|
assertEquals("192.168.4.1", candidate1.getHost().toString());
|
||||||
assertEquals(JidCreate.from("romeo@montague.lit/orchard"), candidate1.getJid());
|
assertEquals(JidCreate.from("romeo@montague.lit/orchard"), candidate1.getJid());
|
||||||
assertEquals(5086, candidate1.getPort());
|
assertEquals(5086, candidate1.getPort());
|
||||||
assertEquals(8257636, candidate1.getPriority());
|
assertEquals(8257636, candidate1.getPriority());
|
||||||
|
@ -98,7 +100,7 @@ public class JingleS5BTransportTest extends SmackTestSuite {
|
||||||
JingleS5BTransportCandidate candidate2 =
|
JingleS5BTransportCandidate candidate2 =
|
||||||
(JingleS5BTransportCandidate) transport.getCandidates().get(1);
|
(JingleS5BTransportCandidate) transport.getCandidates().get(1);
|
||||||
assertEquals("hutr46fe", candidate2.getCandidateId());
|
assertEquals("hutr46fe", candidate2.getCandidateId());
|
||||||
assertEquals("24.24.24.1", candidate2.getHost());
|
assertEquals("24.24.24.1", candidate2.getHost().toString());
|
||||||
assertEquals(JidCreate.from("romeo@montague.lit/orchard"), candidate2.getJid());
|
assertEquals(JidCreate.from("romeo@montague.lit/orchard"), candidate2.getJid());
|
||||||
assertEquals(5087, candidate2.getPort());
|
assertEquals(5087, candidate2.getPort());
|
||||||
assertEquals(8258636, candidate2.getPriority());
|
assertEquals(8258636, candidate2.getPriority());
|
||||||
|
@ -107,7 +109,7 @@ public class JingleS5BTransportTest extends SmackTestSuite {
|
||||||
JingleS5BTransportCandidate candidate3 =
|
JingleS5BTransportCandidate candidate3 =
|
||||||
(JingleS5BTransportCandidate) transport.getCandidates().get(2);
|
(JingleS5BTransportCandidate) transport.getCandidates().get(2);
|
||||||
assertEquals("xmdh4b7i", candidate3.getCandidateId());
|
assertEquals("xmdh4b7i", candidate3.getCandidateId());
|
||||||
assertEquals("123.456.7.8", candidate3.getHost());
|
assertEquals("123.456.7.8", candidate3.getHost().toString());
|
||||||
assertEquals(JidCreate.domainBareFrom("streamer.shakespeare.lit"), candidate3.getJid());
|
assertEquals(JidCreate.domainBareFrom("streamer.shakespeare.lit"), candidate3.getJid());
|
||||||
assertEquals(7625, candidate3.getPort());
|
assertEquals(7625, candidate3.getPort());
|
||||||
assertEquals(7878787, candidate3.getPriority());
|
assertEquals(7878787, candidate3.getPriority());
|
||||||
|
@ -187,15 +189,15 @@ public class JingleS5BTransportTest extends SmackTestSuite {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void transportCandidateIllegalPriorityTest() throws XmppStringprepException {
|
public void transportCandidateIllegalPriorityTest() throws XmppStringprepException, UnknownHostException {
|
||||||
FullJid jid = JidCreate.fullFrom("test@test.test/test");
|
FullJid jid = JidCreate.fullFrom("test@test.test/test");
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
JingleS5BTransportCandidate candidate = new JingleS5BTransportCandidate(
|
JingleS5BTransportCandidate candidate = new JingleS5BTransportCandidate(
|
||||||
"cid", "host", jid, 5555, -30, JingleS5BTransportCandidate.Type.proxy);
|
"cid", "localhost", jid, 5555, -30, JingleS5BTransportCandidate.Type.proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void transportCandidateIllegalPortTest() throws XmppStringprepException {
|
public void transportCandidateIllegalPortTest() throws XmppStringprepException, UnknownHostException {
|
||||||
FullJid jid = JidCreate.fullFrom("test@test.test/test");
|
FullJid jid = JidCreate.fullFrom("test@test.test/test");
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
JingleS5BTransportCandidate candidate = new JingleS5BTransportCandidate(
|
JingleS5BTransportCandidate candidate = new JingleS5BTransportCandidate(
|
||||||
|
@ -203,9 +205,9 @@ public class JingleS5BTransportTest extends SmackTestSuite {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void candidateFromStreamHostTest() throws XmppStringprepException {
|
public void candidateFromStreamHostTest() throws XmppStringprepException, UnknownHostException {
|
||||||
FullJid jid = JidCreate.fullFrom("test@test.test/test");
|
FullJid jid = JidCreate.fullFrom("test@test.test/test");
|
||||||
String host = "host.address";
|
String host = "localhost";
|
||||||
int port = 1234;
|
int port = 1234;
|
||||||
Bytestream.StreamHost streamHost = new Bytestream.StreamHost(jid, host, port);
|
Bytestream.StreamHost streamHost = new Bytestream.StreamHost(jid, host, port);
|
||||||
|
|
||||||
|
@ -213,7 +215,7 @@ public class JingleS5BTransportTest extends SmackTestSuite {
|
||||||
|
|
||||||
assertEquals(2000, candidate.getPriority());
|
assertEquals(2000, candidate.getPriority());
|
||||||
assertEquals(jid, candidate.getJid());
|
assertEquals(jid, candidate.getJid());
|
||||||
assertEquals(host, candidate.getHost());
|
assertEquals(host, candidate.getHost().toString());
|
||||||
assertEquals(port, candidate.getPort());
|
assertEquals(port, candidate.getPort());
|
||||||
|
|
||||||
assertEquals(streamHost.toXML().toString(), candidate.getStreamHost().toXML().toString());
|
assertEquals(streamHost.toXML().toString(), candidate.getStreamHost().toXML().toString());
|
||||||
|
|
Loading…
Reference in a new issue