SocksSocketFactory.java

 1package eu.siacs.conversations.utils;
 2
 3import java.io.IOException;
 4import java.io.InputStream;
 5import java.io.OutputStream;
 6import java.net.InetAddress;
 7import java.net.InetSocketAddress;
 8import java.net.Socket;
 9import java.nio.ByteBuffer;
10
11import eu.siacs.conversations.Config;
12
13public class SocksSocketFactory {
14
15	private static final byte[] LOCALHOST = new byte[]{127,0,0,1};
16
17	public static void createSocksConnection(Socket socket, String destination, int port) throws IOException {
18		InputStream proxyIs = socket.getInputStream();
19		OutputStream proxyOs = socket.getOutputStream();
20		proxyOs.write(new byte[]{0x05, 0x01, 0x00});
21		byte[] response = new byte[2];
22		proxyIs.read(response);
23		if (response[0] != 0x05 || response[1] != 0x00) {
24			throw new SocksConnectionException("Socks 5 handshake failed");
25		}
26		byte[] dest = destination.getBytes();
27		ByteBuffer request = ByteBuffer.allocate(7 + dest.length);
28		request.put(new byte[]{0x05, 0x01, 0x00, 0x03});
29		request.put((byte) dest.length);
30		request.put(dest);
31		request.putShort((short) port);
32		proxyOs.write(request.array());
33		response = new byte[7 + dest.length];
34		proxyIs.read(response);
35		if (response[1] != 0x00) {
36			if (response[1] == 0x04) {
37				throw new HostNotFoundException("Host unreachable");
38			}
39			if (response[1] == 0x05) {
40				throw new HostNotFoundException("Connection refused");
41			}
42			throw new SocksConnectionException("Unable to connect to destination "+(int) (response[1]));
43		}
44	}
45
46	public static boolean contains(byte needle, byte[] haystack) {
47		for(byte hay : haystack) {
48			if (hay == needle) {
49				return true;
50			}
51		}
52		return false;
53	}
54
55	public static Socket createSocket(InetSocketAddress address, String destination, int port) throws IOException {
56		Socket socket = new Socket();
57		try {
58			socket.connect(address, Config.CONNECT_TIMEOUT * 1000);
59		} catch (IOException e) {
60			throw new SocksProxyNotFoundException();
61		}
62		createSocksConnection(socket, destination, port);
63		return socket;
64	}
65
66	public static Socket createSocketOverTor(String destination, int port) throws IOException {
67		return createSocket(new InetSocketAddress(InetAddress.getByAddress(LOCALHOST), 9050), destination, port);
68	}
69
70	private static class SocksConnectionException extends IOException {
71		SocksConnectionException(String message) {
72			super(message);
73		}
74	}
75
76	public static class SocksProxyNotFoundException extends IOException {
77
78	}
79
80	public static class HostNotFoundException extends SocksConnectionException {
81		HostNotFoundException(String message) {
82			super(message);
83		}
84	}
85}