snf4j / snf4j
Showing 21 of 39 files from the diff.

@@ -0,0 +1,61 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
enum Socks4Status {
29 +
	
30 +
	SUCCESS(90, "Request granted"),
31 +
	REJECTED_OR_FAILED(91, "Request rejected or failed"),
32 +
	IDENTD_UNREACHABLE(92, "Request rejected becasue SOCKS server cannot connect to identd on the client"),
33 +
	IDENTD_AUTH_FAILURE(93, "Request rejected because the client program and identd report different user-ids"),
34 +
	UNKNOWN(-1, "Unknown");
35 +
	
36 +
	private final int code;
37 +
	
38 +
	private final String description;
39 +
	
40 +
	Socks4Status(int code, String description) {
41 +
		this.code = code;
42 +
		this.description = description;
43 +
	}
44 +
	
45 +
	public int code() {
46 +
		return code;
47 +
	}
48 +
	
49 +
	public String description() {
50 +
		return description;
51 +
	}
52 +
	
53 +
	public static Socks4Status valueOf(int code) {
54 +
		for (Socks4Status value: values()) {
55 +
			if (value.code == code) {
56 +
				return value;
57 +
			}
58 +
		}
59 +
		return UNKNOWN;
60 +
	}
61 +
}

@@ -684,6 +684,11 @@
Loading
684 684
		return timer;
685 685
	}
686 686
	
687 +
	@Override
688 +
	public boolean isDataCopyingOptimized() {
689 +
		return optimizeCopying;
690 +
	}
691 +
	
687 692
	@Override
688 693
	public ByteBuffer allocate(int capacity) {
689 694
		return allocator.allocate(capacity);

@@ -35,6 +35,7 @@
Loading
35 35
import org.snf4j.core.factory.ISessionStructureFactory;
36 36
import org.snf4j.core.handler.SessionEvent;
37 37
import org.snf4j.core.session.ISessionConfig;
38 +
import org.snf4j.core.session.IStreamSession;
38 39
39 40
/**
40 41
 * Handles client proxy connections via the HTTP tunneling protocol. For more
@@ -89,6 +90,7 @@
Loading
89 90
	 * 
90 91
	 * @param uri the URI identifying the remote host to which the HTTP tunnel
91 92
	 *            should be established
93 +
	 * @throws IllegalArgumentException if the uri is null
92 94
	 */
93 95
	public HttpProxyHandler(URI uri) {	
94 96
		this(uri, false, null, null);
@@ -105,6 +107,7 @@
Loading
105 107
	 *               should be established
106 108
	 * @param config the session configuration object, or {@code null} to use the
107 109
	 *               default configuration
110 +
	 * @throws IllegalArgumentException if the uri is null
108 111
	 */
109 112
	public HttpProxyHandler(URI uri, ISessionConfig config) {	
110 113
		this(uri, false, config, null);
@@ -124,6 +127,7 @@
Loading
124 127
	 * @param factory the factory that will be used to configure the internal
125 128
	 *                structure of the associated session, or {@code null} to use
126 129
	 *                the default factory
130 +
	 * @throws IllegalArgumentException if the uri is null
127 131
	 */
128 132
	public HttpProxyHandler(URI uri, ISessionConfig config, ISessionStructureFactory factory) {	
129 133
		this(uri, false, config, factory);
@@ -143,6 +147,7 @@
Loading
143 147
	 *                             terminators in the responses from a HTTP proxy
144 148
	 *                             server, or otherwise (default option) only CRLF
145 149
	 *                             will be allowed
150 +
	 * @throws IllegalArgumentException if the uri is null
146 151
	 */
147 152
	public HttpProxyHandler(URI uri, boolean allowBothTerminators) {	
148 153
		this(uri, allowBothTerminators, null, null);
@@ -164,6 +169,7 @@
Loading
164 169
	 *                             will be allowed
165 170
	 * @param config               the session configuration object, or {@code null}
166 171
	 *                             to use the default configuration
172 +
	 * @throws IllegalArgumentException if the uri is null
167 173
	 */
168 174
	public HttpProxyHandler(URI uri, boolean allowBothTerminators, ISessionConfig config) {	
169 175
		this(uri, allowBothTerminators, config, null);
@@ -188,6 +194,7 @@
Loading
188 194
	 * @param factory              the factory that will be used to configure the
189 195
	 *                             internal structure of the associated session, or
190 196
	 *                             {@code null} to use the default factory
197 +
	 * @throws IllegalArgumentException if the uri is null
191 198
	 */
192 199
	public HttpProxyHandler(URI uri, boolean allowBothTerminators, ISessionConfig config, ISessionStructureFactory factory) {	
193 200
		super(config, factory);
@@ -210,6 +217,7 @@
Loading
210 217
	 * @param connectionTimeout the proxy connection timeout in milliseconds, or
211 218
	 *                          {@code 0} to wait an infinite amount of time for 
212 219
	 *                          establishing the HTTP tunnel.
220 +
	 * @throws IllegalArgumentException if the uri is null
213 221
	 */
214 222
	public HttpProxyHandler(URI uri, long connectionTimeout) {
215 223
		this(uri, connectionTimeout, false);
@@ -229,6 +237,7 @@
Loading
229 237
	 *                          establishing the HTTP tunnel.
230 238
	 * @param config            the session configuration object, or {@code null} to
231 239
	 *                          use the default configuration
240 +
	 * @throws IllegalArgumentException if the uri is null
232 241
	 */
233 242
	public HttpProxyHandler(URI uri, long connectionTimeout, ISessionConfig config) {
234 243
		this(uri, connectionTimeout, false, config, null);
@@ -251,6 +260,7 @@
Loading
251 260
	 * @param factory           the factory that will be used to configure the
252 261
	 *                          internal structure of the associated session, or
253 262
	 *                          {@code null} to use the default factory
263 +
	 * @throws IllegalArgumentException if the uri is null
254 264
	 */
255 265
	public HttpProxyHandler(URI uri, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
256 266
		this(uri, connectionTimeout, false, config, factory);
@@ -272,6 +282,7 @@
Loading
272 282
	 *                             terminators in the responses from a HTTP proxy
273 283
	 *                             server, or otherwise (default option) only CRLF
274 284
	 *                             will be allowed
285 +
	 * @throws IllegalArgumentException if the uri is null
275 286
	 */
276 287
	public HttpProxyHandler(URI uri, long connectionTimeout, boolean allowBothTerminators) {
277 288
		this(uri, connectionTimeout, allowBothTerminators, null, null);
@@ -296,6 +307,7 @@
Loading
296 307
	 *                             will be allowed
297 308
	 * @param config               the session configuration object, or {@code null}
298 309
	 *                             to use the default configuration
310 +
	 * @throws IllegalArgumentException if the uri is null
299 311
	 */
300 312
	public HttpProxyHandler(URI uri, long connectionTimeout, boolean allowBothTerminators, ISessionConfig config) {
301 313
		this(uri, connectionTimeout, allowBothTerminators, config, null);
@@ -323,6 +335,7 @@
Loading
323 335
	 * @param factory              the factory that will be used to configure the
324 336
	 *                             internal structure of the associated session, or
325 337
	 *                             {@code null} to use the default factory
338 +
	 * @throws IllegalArgumentException if the uri is null
326 339
	 */
327 340
	public HttpProxyHandler(URI uri, long connectionTimeout, boolean allowBothTerminators, ISessionConfig config, ISessionStructureFactory factory) {
328 341
		super(connectionTimeout, config, factory);
@@ -532,6 +545,7 @@
Loading
532 545
			host = toBytes(uriHost);
533 546
		}
534 547
		
548 +
		IStreamSession session = getSession();
535 549
		ByteBuffer frame;
536 550
		
537 551
		synchronized (headers) {
@@ -548,7 +562,7 @@
Loading
548 562
				+ headersLength
549 563
				+ CRLF.length;
550 564
		
551 -
			frame = getSession().allocate(length);
565 +
			frame = session.allocate(length);
552 566
			frame.put(HTTP_CONNECT);
553 567
			frame.put(SP);
554 568
			frame.put(fullHost);
@@ -568,7 +582,10 @@
Loading
568 582
		
569 583
		frame.put(CRLF);
570 584
		frame.flip();
571 -
		getSession().writenf(frame);
585 +
		session.writenf(frame);
586 +
		if (!session.isDataCopyingOptimized()) {
587 +
			session.release(frame);
588 +
		}
572 589
	}
573 590
574 591
	@Override

@@ -0,0 +1,124 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.net.InetSocketAddress;
29 +
import java.nio.ByteBuffer;
30 +
import java.nio.charset.StandardCharsets;
31 +
32 +
import org.snf4j.core.util.NetworkUtil;
33 +
34 +
class Socks4CommandState extends AbstractSocksState implements ISocks4 {
35 +
36 +
	private final static byte REPLY_VERSION = 0;
37 +
38 +
	private final static int RESPONSE_SIZE = 8;
39 +
	
40 +
	private final static byte[] DOMAIN_MARKER = new byte[] {0,0,0,1};
41 +
	
42 +
	final static int STATUS_INDEX = 1;
43 +
44 +
	final static int IP_INDEX = 4;
45 +
46 +
	final static int PORT_INDEX = 2;
47 +
	
48 +
	private final Socks4Command command;
49 +
	
50 +
	private final String username;
51 +
	
52 +
	Socks4CommandState(Socks4ProxyHandler handler, Socks4Command command, String username) {
53 +
		super(handler);
54 +
		this.command = command;
55 +
		this.username = username == null ? "" : username;
56 +
	}
57 +
58 +
	@Override
59 +
	int responseSize() {
60 +
		return RESPONSE_SIZE;
61 +
	}
62 +
63 +
	@Override
64 +
	AbstractSocksState read(byte[] data) {
65 +
		if (data[VER_INDEX] != REPLY_VERSION) {
66 +
			throw new ProxyConnectionException("Unsupported SOCKS4 reply version: " + data[0] + " (expected: 0)");
67 +
		}
68 +
		
69 +
		int statusCode = (int)data[STATUS_INDEX] & 0xff;
70 +
		Socks4Status status = Socks4Status.valueOf(statusCode);
71 +
		int replyCount = handler.reply(new Socks4Reply(
72 +
				statusCode, NetworkUtil.ipv4ToString(data, IP_INDEX), NetworkUtil.toPort(data,PORT_INDEX)));
73 +
		
74 +
		if (status != Socks4Status.SUCCESS) {
75 +
			throw new ProxyConnectionException("SOCKS4 proxy response status code: " + statusCode);
76 +
		}
77 +
		if (command == Socks4Command.CONNECT || replyCount == 2) {
78 +
			return null;
79 +
		}
80 +
		return this;
81 +
	}
82 +
83 +
	@Override
84 +
	void handleReady() {
85 +
		InetSocketAddress address = handler.getAddress();
86 +
		byte[] usernameBytes = username.getBytes(StandardCharsets.US_ASCII);
87 +
		String host;
88 +
		byte[] ipv4, hostBytes;
89 +
		int len;
90 +
		
91 +
		if (address.isUnresolved()) {
92 +
			host = address.getHostString();
93 +
		}
94 +
		else {
95 +
			host = address.getAddress().getHostAddress();
96 +
		}
97 +
		
98 +
		ipv4 = NetworkUtil.ipv4ToBytes(host);
99 +
		len = 1+1+2+4+usernameBytes.length+1;
100 +
		if (ipv4 != null) {
101 +
			hostBytes = null;
102 +
		}
103 +
		else {
104 +
			hostBytes = host.getBytes(StandardCharsets.US_ASCII);
105 +
			ipv4 = DOMAIN_MARKER;
106 +
			len += hostBytes.length + 1;
107 +
		}
108 +
		
109 +
		ByteBuffer buf = handler.getSession().allocate(len);
110 +
		
111 +
		buf.put(VERSION);
112 +
		buf.put(command.code());
113 +
		buf.putShort((short)address.getPort());
114 +
		buf.put(ipv4);
115 +
		buf.put(usernameBytes);
116 +
		buf.put((byte)0);
117 +
		if (hostBytes != null) {
118 +
			buf.put(hostBytes);
119 +
			buf.put((byte)0);
120 +
		}
121 +
		handler.flipAndWrite(buf);
122 +
	}
123 +
124 +
}

@@ -0,0 +1,75 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
class Socks5Reply implements ISocksReply {
29 +
	
30 +
	private final int status;
31 +
	
32 +
	private final String address;
33 +
	
34 +
	private final SocksAddressType addressType;
35 +
	
36 +
	private final int port;
37 +
	
38 +
	Socks5Reply(int status, SocksAddressType addressType, String address, int port) {
39 +
		this.status = status;
40 +
		this.addressType = addressType;
41 +
		this.address = address;
42 +
		this.port = port;
43 +
	}
44 +
	
45 +
	@Override
46 +
	public boolean isSuccessful() {
47 +
		return status == Socks5Status.SUCCESS.code();
48 +
	}
49 +
50 +
	@Override
51 +
	public int getStatus() {
52 +
		return status;
53 +
	}
54 +
55 +
	@Override
56 +
	public String getStatusDescription() {
57 +
		return Socks5Status.valueOf(status).description();
58 +
	}
59 +
60 +
	@Override
61 +
	public int getPort() {
62 +
		return port;
63 +
	}
64 +
65 +
	@Override
66 +
	public String getAddress() {
67 +
		return address;
68 +
	}
69 +
70 +
	@Override
71 +
	public SocksAddressType getAddressType() {
72 +
		return addressType;
73 +
	}
74 +
75 +
}

@@ -0,0 +1,53 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
/**
29 +
 * An {@code enum} that defines types of commands for the SOCKS5 proxy handler.
30 +
 * 
31 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
32 +
 */
33 +
public enum Socks5Command {
34 +
	
35 +
	/** The CONNECT command */
36 +
	CONNECT((byte)1),
37 +
	
38 +
	/** The BIND command */
39 +
	BIND((byte)2),
40 +
	
41 +
	/** The UDP_ASSOCIATE command */
42 +
	UDP_ASSOCIATE((byte)3);
43 +
	
44 +
	private final byte code;
45 +
	
46 +
	Socks5Command(byte code) {
47 +
		this.code = code;
48 +
	}
49 +
	
50 +
	byte code() {
51 +
		return code;
52 +
	}
53 +
}

@@ -1,7 +1,7 @@
Loading
1 1
/*
2 2
 * -------------------------------- MIT License --------------------------------
3 3
 * 
4 -
 * Copyright (c) 2020 SNF4J contributors
4 +
 * Copyright (c) 2020-2021 SNF4J contributors
5 5
 * 
6 6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7
 * of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +26,7 @@
Loading
26 26
package org.snf4j.core.allocator;
27 27
28 28
import java.nio.ByteBuffer;
29 +
import java.nio.ByteOrder;
29 30
30 31
class Cache {
31 32
	
@@ -132,6 +133,7 @@
Loading
132 133
			
133 134
			cache[size] = null;
134 135
			b.clear();
136 +
			b.order(ByteOrder.BIG_ENDIAN);
135 137
			touchAll(touch, touchAll);
136 138
			return b;
137 139
		}

@@ -0,0 +1,66 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
enum Socks5Status {
29 +
    SUCCESS(0, "Succeeded"),
30 +
    FAILURE(1, "General SOCKS server failure"),
31 +
    FORBIDDEN(2, "Connection not allowed by ruleset"),
32 +
    NETWORK_UNREACHABLE(3, "Network unreachable"),
33 +
    HOST_UNREACHABLE(4, "Host unreachable"),
34 +
    CONNECTION_REFUSED(5, "Connection refused"),
35 +
    TTL_EXPIRED(6, "TTL expired"),
36 +
    COMMAND_UNSUPPORTED(7, "Command not supported"),
37 +
    ADDRESS_UNSUPPORTED(8, "Address type not supported"),
38 +
    UNKNOWN(-1, "Unknown");
39 +
	
40 +
	private final int code;
41 +
	
42 +
	private final String description;
43 +
	
44 +
	Socks5Status(int code, String description) {
45 +
		this.code = code;
46 +
		this.description = description;
47 +
	}
48 +
	
49 +
	public int code() {
50 +
		return code;
51 +
	}
52 +
	
53 +
	public String description() {
54 +
		return description;
55 +
	}
56 +
	
57 +
	public static Socks5Status valueOf(int code) {
58 +
		for (Socks5Status value: values()) {
59 +
			if (value.code == code) {
60 +
				return value;
61 +
			}
62 +
		}
63 +
		return UNKNOWN;
64 +
	}
65 +
66 +
}

@@ -0,0 +1,198 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.net.InetSocketAddress;
29 +
import java.nio.ByteBuffer;
30 +
import java.nio.charset.StandardCharsets;
31 +
32 +
import org.snf4j.core.util.NetworkUtil;
33 +
34 +
class Socks5CommandState extends AbstractSocksState implements ISocks5 {
35 +
	
36 +
	final static int STATUS_INDEX = 1;
37 +
38 +
	final static int ATYP_INDEX = 3;
39 +
40 +
	final static int ADDR_INDEX = 4;
41 +
	
42 +
	private final Socks5Command command;
43 +
	
44 +
	Socks5CommandState(Socks5ProxyHandler handler, Socks5Command command) {
45 +
		super(handler);
46 +
		this.command = command;
47 +
	}
48 +
49 +
	private int expectedLength(byte atyp, byte a0) {
50 +
		int alen;
51 +
		
52 +
		switch (atyp) {
53 +
		case 1:
54 +
			alen = 4;
55 +
			break;
56 +
			
57 +
		case 3:
58 +
			alen = 1 + ((int)a0 & 0xff);
59 +
			break;
60 +
			
61 +
		case 4:
62 +
			alen = 16;
63 +
			break;
64 +
			
65 +
		default:
66 +
			//unexpected address type, set to 0 and fail during parsing
67 +
			alen = 0;
68 +
		}
69 +
		return alen + 6;
70 +
	}
71 +
72 +
	@Override
73 +
	int available(ByteBuffer data, boolean flipped) {
74 +
		int len = length(data, flipped);
75 +
76 +
		if (len >= 6) {
77 +
			ByteBuffer buf = flipped ? data : (ByteBuffer)data.duplicate().flip();
78 +
			int expLen = expectedLength(buf.get(3), buf.get(4));
79 +
			
80 +
			if (len >= expLen) {
81 +
				return expLen;
82 +
			}
83 +
		}
84 +
		return 0;
85 +
	}
86 +
87 +
	@Override
88 +
	int available(byte[] data, int off, int len) {
89 +
		if (len >= 6) {
90 +
			int expLen = expectedLength(data[off+3], data[off+4]);
91 +
			
92 +
			if (len >= expLen) {
93 +
				return expLen;
94 +
			}
95 +
		}
96 +
		return 0;
97 +
	}
98 +
99 +
	@Override
100 +
	int responseSize() {
101 +
		//Ignored as we override available methods
102 +
		return 0;
103 +
	}
104 +
105 +
	@Override
106 +
	AbstractSocksState read(byte[] data) {
107 +
		if (data[VER_INDEX] != VERSION) {
108 +
			throw new ProxyConnectionException("Unsupported SOCKS5 reply version: " + data[VER_INDEX]);
109 +
		}
110 +
		
111 +
		int statusCode = (int)data[STATUS_INDEX] & 0xff;
112 +
		Socks5Status status = Socks5Status.valueOf(statusCode);
113 +
		SocksAddressType addrType = SocksAddressType.valueOf(data[ATYP_INDEX]);
114 +
		String addr;
115 +
		int addrLen;
116 +
		
117 +
		if (addrType == null) {
118 +
			throw new ProxyConnectionException("Unexpected address type: " + data[ATYP_INDEX]);
119 +
		}
120 +
		
121 +
		switch (addrType) {
122 +
		case IPV4:
123 +
			addrLen = 4;
124 +
			addr = NetworkUtil.ipv4ToString(data, ADDR_INDEX);
125 +
			break;
126 +
			
127 +
		case IPV6:
128 +
			addrLen = 16;
129 +
			addr = NetworkUtil.ipv6ToString(data, ADDR_INDEX, false);
130 +
			break;
131 +
			
132 +
		default:
133 +
			addrLen = (int)data[ADDR_INDEX] & 0xff;
134 +
			addr = new String(data, ADDR_INDEX+1, addrLen++, StandardCharsets.US_ASCII);
135 +
			break;
136 +
		}
137 +
		
138 +
		int replyCount = handler.reply(new Socks5Reply(statusCode, addrType, addr, NetworkUtil.toPort(data,ADDR_INDEX+addrLen)));
139 +
		
140 +
		if (status != Socks5Status.SUCCESS) {
141 +
			throw new ProxyConnectionException("SOCKS5 proxy response status code: " + statusCode);
142 +
		}
143 +
		if (command != Socks5Command.BIND || replyCount == 2) {
144 +
			return null;
145 +
		}
146 +
		return this;
147 +
	}
148 +
149 +
	@Override
150 +
	void handleReady() {
151 +
		InetSocketAddress address = handler.getAddress();
152 +
		SocksAddressType addrType = null;
153 +
		int addrLen = 0;
154 +
		String host;
155 +
		byte[] addrBytes;
156 +
		
157 +
		if (address.isUnresolved()) {
158 +
			host = address.getHostString();
159 +
		}
160 +
		else {
161 +
			host = address.getAddress().getHostAddress();
162 +
		}
163 +
		addrBytes = NetworkUtil.ipv4ToBytes(host);
164 +
		if (addrBytes == null) {
165 +
			addrBytes = NetworkUtil.ipv6ToBytes(host);
166 +
			if (addrBytes != null) {
167 +
				addrType = SocksAddressType.IPV6;
168 +
				addrLen = 16;
169 +
			}
170 +
		}
171 +
		else {
172 +
			addrType = SocksAddressType.IPV4;
173 +
			addrLen = 4;
174 +
		}
175 +
		if (addrBytes == null) {
176 +
			addrBytes = host.getBytes(StandardCharsets.US_ASCII);
177 +
			if (addrBytes.length > 255) {
178 +
				throw new ProxyConnectionException("Destination domain name length too long");
179 +
			}
180 +
			addrType = SocksAddressType.DOMAIN;
181 +
			addrLen = addrBytes.length + 1;
182 +
		}
183 +
		
184 +
		ByteBuffer buf = handler.getSession().allocate(6 + addrLen);
185 +
		
186 +
		buf.put(VERSION);
187 +
		buf.put(command.code());
188 +
		buf.put((byte)0);
189 +
		buf.put(addrType.code());
190 +
		if (addrType == SocksAddressType.DOMAIN) {
191 +
			buf.put((byte)addrBytes.length);
192 +
		}
193 +
		buf.put(addrBytes);
194 +
		buf.putShort((short)address.getPort());
195 +
		handler.flipAndWrite(buf);
196 +
	}
197 +
198 +
}

@@ -0,0 +1,225 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.net.InetSocketAddress;
29 +
import java.nio.ByteBuffer;
30 +
import java.util.ArrayList;
31 +
import java.util.LinkedList;
32 +
import java.util.List;
33 +
34 +
import org.snf4j.core.factory.ISessionStructureFactory;
35 +
import org.snf4j.core.handler.SessionEvent;
36 +
import org.snf4j.core.session.ISessionConfig;
37 +
import org.snf4j.core.session.IStreamSession;
38 +
39 +
/**
40 +
 * Base implementation for handlers processing client connections via SOCKS
41 +
 * proxy protocols.
42 +
 * 
43 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
44 +
 */
45 +
abstract public class AbstractSocksProxyHandler extends AbstractProxyHandler {
46 +
	
47 +
	private final InetSocketAddress address;
48 +
	
49 +
	private final List<ISocksReply> replies = new ArrayList<ISocksReply>(2);
50 +
	
51 +
	private List<ISocksReplyListener> replyListeners;
52 +
	
53 +
	volatile AbstractSocksState state;
54 +
	
55 +
	/**
56 +
	 * Constructs a SOCKS proxy connection handler with the specified destination
57 +
	 * address, connection timeout, configuration and factory.
58 +
	 * <p>
59 +
	 * NOTE: The connection timeout will have no effect if the associated session
60 +
	 * does not support a session timer.
61 +
	 * 
62 +
	 * @param address           the destination address
63 +
	 * @param connectionTimeout the SOCKS proxy connection timeout in milliseconds,
64 +
	 *                          or {@code 0} to wait an infinite amount of time for
65 +
	 *                          establishing of the SOCKS connection.
66 +
	 * @param config            the session configuration object, or {@code null} to
67 +
	 *                          use the default configuration
68 +
	 * @param factory           the factory that will be used to configure the
69 +
	 *                          internal structure of the associated session, or
70 +
	 *                          {@code null} to use the default factory
71 +
	 * @throws IllegalArgumentException if the address is null
72 +
	 */
73 +
	protected AbstractSocksProxyHandler(InetSocketAddress address, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
74 +
		super(connectionTimeout, config, factory);
75 +
		checkNull(address, "address");
76 +
		this.address = address;
77 +
	}
78 +
79 +
	/**
80 +
	 * Constructs a SOCKS proxy connection handler with the specified destination
81 +
	 * address, the default (10 seconds) connection timeout, configuration and factory.
82 +
	 * <p>
83 +
	 * NOTE: The connection timeout will have no effect if the associated session
84 +
	 * does not support a session timer.
85 +
	 * 
86 +
	 * @param address           the destination address
87 +
	 * @param config            the session configuration object, or {@code null} to
88 +
	 *                          use the default configuration
89 +
	 * @param factory           the factory that will be used to configure the
90 +
	 *                          internal structure of the associated session, or
91 +
	 *                          {@code null} to use the default factory
92 +
	 * @throws IllegalArgumentException if the address is null
93 +
	 */
94 +
	protected AbstractSocksProxyHandler(InetSocketAddress address, ISessionConfig config, ISessionStructureFactory factory) {
95 +
		super(config, factory);
96 +
		checkNull(address, "address");
97 +
		this.address = address;
98 +
	}
99 +
	
100 +
	final void checkNull(Object value, String name) {
101 +
		if (value == null) {
102 +
			throw new IllegalArgumentException(name + " is null");
103 +
		}
104 +
	}
105 +
	
106 +
	/**
107 +
	 * Returns the destination address.
108 +
	 * 
109 +
	 * @return the destination address
110 +
	 */
111 +
	public InetSocketAddress getAddress() {
112 +
		return address;
113 +
	}
114 +
115 +
	/**
116 +
	 * Returns replies sent from the SOCKS server.
117 +
	 * 
118 +
	 * @return the replies sent from the SOCKS server
119 +
	 */
120 +
	public ISocksReply[] getReplies() {
121 +
		ISocksReply[] replyArray;
122 +
		
123 +
		synchronized (replies) {
124 +
			replyArray = replies.toArray(new ISocksReply[replies.size()]);
125 +
		}
126 +
		return replyArray;
127 +
	}
128 +
	
129 +
	/**
130 +
	 * Adds a listener for replies sent from the SOCKS server
131 +
	 * 
132 +
	 * @param listener a listener for replies
133 +
	 */
134 +
	public void addReplyListener(ISocksReplyListener listener) {
135 +
		synchronized (replies) {
136 +
			if (replyListeners == null) {
137 +
				replyListeners = new LinkedList<ISocksReplyListener>();
138 +
			}
139 +
			replyListeners.add(listener);
140 +
		}
141 +
	}
142 +
	
143 +
	int reply(ISocksReply reply) {
144 +
		ISocksReplyListener[] listeners;
145 +
		int replyIndex;
146 +
		
147 +
		synchronized (replies) {
148 +
			replies.add(reply);
149 +
			replyIndex = replies.size();
150 +
			if (replyListeners == null) {
151 +
				return replyIndex;
152 +
			}
153 +
			listeners = replyListeners.toArray(new ISocksReplyListener[replyListeners.size()]);
154 +
		}	
155 +
		for (ISocksReplyListener listener: listeners) {
156 +
			listener.replyReceived(reply, replyIndex);
157 +
		}
158 +
		return replyIndex;
159 +
	}
160 +
	
161 +
	void flipAndWrite(ByteBuffer buf) {
162 +
		IStreamSession session = getSession(); 
163 +
		
164 +
		buf.flip();
165 +
		session.writenf(buf);
166 +
		if (!session.isDataCopyingOptimized()) {
167 +
			session.release(buf);
168 +
		}
169 +
	}
170 +
171 +
	@Override
172 +
	public int available(ByteBuffer data, boolean flipped) {
173 +
		return state.available(data, flipped);
174 +
	}
175 +
	
176 +
	@Override
177 +
	public int available(byte[] data, int off, int len) {
178 +
		return state.available(data, off, len);
179 +
	}
180 +
	
181 +
	@Override
182 +
	public void read(ByteBuffer data) {
183 +
		byte[] bytes = new byte[data.remaining()];
184 +
		
185 +
		data.get(bytes);
186 +
		getSession().release(data);
187 +
		read(bytes);
188 +
	}
189 +
190 +
	@Override
191 +
	public void read(byte[] data) {
192 +
		AbstractSocksState nextState = state.read(data);
193 +
		
194 +
		if (nextState != state) {
195 +
			if (nextState == null) {
196 +
				state = new SocksDoneState(this);
197 +
				getSession().getPipeline().markDone();
198 +
				getSession().close();
199 +
			}
200 +
			else {
201 +
				state = nextState;
202 +
				state.handleReady();
203 +
			}
204 +
		}
205 +
	}
206 +
207 +
	@Override
208 +
	protected void handleReady() throws Exception {
209 +
		state.handleReady();
210 +
	}	
211 +
	
212 +
	@Override
213 +
	public void read(Object msg) {
214 +
	}
215 +
216 +
	@Override
217 +
	public void event(SessionEvent event) {
218 +
		if (event == SessionEvent.OPENED) {
219 +
			getSession().getPipeline().markUndone(new ProxyConnectionException("Incomplete " + protocol() + " proxy protocol"));
220 +
		}
221 +
		super.event(event);
222 +
	}
223 +
224 +
	abstract String protocol();
225 +
}

@@ -0,0 +1,44 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
enum Socks5AuthMethod {
29 +
	
30 +
	NO_AUTH((byte)0),
31 +
	GSSAPI((byte)1),
32 +
	PASSWORD((byte)2),
33 +
	UNACCEPTED((byte)0xff);
34 +
	
35 +
	private final byte code;
36 +
	
37 +
	Socks5AuthMethod(byte code) {
38 +
		this.code = code;
39 +
	}
40 +
	
41 +
	public byte code() {
42 +
		return code;
43 +
	}
44 +
}

@@ -0,0 +1,50 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
/**
29 +
 * An {@code enum} that defines types of commands for the SOCKS4 proxy handler.
30 +
 * 
31 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
32 +
 */
33 +
public enum Socks4Command {
34 +
	
35 +
	/** The CONNECT command */
36 +
	CONNECT((byte)1),
37 +
	
38 +
	/** The BIND command */
39 +
	BIND((byte)2);
40 +
	
41 +
	private final byte code;
42 +
	
43 +
	Socks4Command(byte code) {
44 +
		this.code = code;
45 +
	}
46 +
	
47 +
	byte code() {
48 +
		return code;
49 +
	}
50 +
}

@@ -0,0 +1,583 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.net.InetSocketAddress;
29 +
import org.snf4j.core.factory.ISessionStructureFactory;
30 +
import org.snf4j.core.session.ISessionConfig;
31 +
32 +
/**
33 +
 * Handles client proxy connections via the SOCKS Protocol Version 5. For more
34 +
 * details about the protocol refer to RFC 1928.
35 +
 * 
36 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
37 +
 */
38 +
public class Socks5ProxyHandler extends AbstractSocksProxyHandler {
39 +
	
40 +
	private final Socks5PasswordAuthState passwordAuthState;
41 +
42 +
	private final Socks5CommandState commandState;
43 +
	
44 +
	/**
45 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
46 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command and the
47 +
	 * default (10 seconds) connection timeout.
48 +
	 * <p>
49 +
	 * NOTE: The connection timeout will have no effect if the associated session
50 +
	 * does not support a session timer.
51 +
	 * 
52 +
	 * @param address the destination address to the host to which the connection
53 +
	 *                should be proxied
54 +
	 * @throws IllegalArgumentException if the address is null
55 +
	 */
56 +
	public Socks5ProxyHandler(InetSocketAddress address) {
57 +
		this(address, Socks5Command.CONNECT, null, null, null, null);
58 +
	}
59 +
60 +
	/**
61 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
62 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, the
63 +
	 * default (10 seconds) connection timeout and configuration.
64 +
	 * <p>
65 +
	 * NOTE: The connection timeout will have no effect if the associated session
66 +
	 * does not support a session timer.
67 +
	 * 
68 +
	 * @param address the destination address to the host to which the connection
69 +
	 *                should be proxied
70 +
	 * @param config  the session configuration object, or {@code null} to use the
71 +
	 *                default configuration
72 +
	 * @throws IllegalArgumentException if the address is null
73 +
	 */
74 +
	public Socks5ProxyHandler(InetSocketAddress address, ISessionConfig config) {
75 +
		this(address, Socks5Command.CONNECT, null, null, config, null);
76 +
	}
77 +
78 +
	/**
79 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
80 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, the
81 +
	 * default (10 seconds) connection timeout, configuration and factory.
82 +
	 * <p>
83 +
	 * NOTE: The connection timeout will have no effect if the associated session
84 +
	 * does not support a session timer.
85 +
	 * 
86 +
	 * @param address the destination address to the host to which the connection
87 +
	 *                should be proxied
88 +
	 * @param config  the session configuration object, or {@code null} to use the
89 +
	 *                default configuration
90 +
	 * @param factory the factory that will be used to configure the internal
91 +
	 *                structure of the associated session, or {@code null} to use
92 +
	 *                the default factory
93 +
	 * @throws IllegalArgumentException if the address is null
94 +
	 */
95 +
	public Socks5ProxyHandler(InetSocketAddress address, ISessionConfig config, ISessionStructureFactory factory) {
96 +
		this(address, Socks5Command.CONNECT, null, null, config, factory);
97 +
	}
98 +
	
99 +
	/**
100 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
101 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, user's
102 +
	 * name/password and the default (10 seconds) connection timeout.
103 +
	 * <p>
104 +
	 * NOTE: The connection timeout will have no effect if the associated session
105 +
	 * does not support a session timer.
106 +
	 * 
107 +
	 * @param address  the destination address to the host to which the connection
108 +
	 *                 should be proxied
109 +
	 * @param username the user's name, or {@code null} for an empty name
110 +
	 * @param password the user's password, or {@code null} for an empty password
111 +
	 * @throws IllegalArgumentException if the address is null
112 +
	 */
113 +
	public Socks5ProxyHandler(InetSocketAddress address, String username, String password) {
114 +
		this(address, Socks5Command.CONNECT, username, password, null, null);
115 +
	}
116 +
117 +
	/**
118 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
119 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, user's
120 +
	 * name/password, the default (10 seconds) connection timeout and configuration.
121 +
	 * <p>
122 +
	 * NOTE: The connection timeout will have no effect if the associated session
123 +
	 * does not support a session timer.
124 +
	 * 
125 +
	 * @param address  the destination address to the host to which the connection
126 +
	 *                 should be proxied
127 +
	 * @param username the user's name, or {@code null} for an empty name
128 +
	 * @param password the user's password, or {@code null} for an empty password
129 +
	 * @param config   the session configuration object, or {@code null} to use the
130 +
	 *                 default configuration
131 +
	 * @throws IllegalArgumentException if the address is null
132 +
	 */
133 +
	public Socks5ProxyHandler(InetSocketAddress address, String username, String password, ISessionConfig config) {
134 +
		this(address, Socks5Command.CONNECT, username, password, config, null);
135 +
	}
136 +
137 +
	/**
138 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
139 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, user's
140 +
	 * name/password, the default (10 seconds) connection timeout, configuration and
141 +
	 * factory.
142 +
	 * <p>
143 +
	 * NOTE: The connection timeout will have no effect if the associated session
144 +
	 * does not support a session timer.
145 +
	 * 
146 +
	 * @param address  the destination address to the host to which the connection
147 +
	 *                 should be proxied
148 +
	 * @param username the user's name, or {@code null} for an empty name
149 +
	 * @param password the user's password, or {@code null} for an empty password
150 +
	 * @param config   the session configuration object, or {@code null} to use the
151 +
	 *                 default configuration
152 +
	 * @param factory  the factory that will be used to configure the internal
153 +
	 *                 structure of the associated session, or {@code null} to use
154 +
	 *                 the default factory
155 +
	 * @throws IllegalArgumentException if the address is null
156 +
	 */
157 +
	public Socks5ProxyHandler(InetSocketAddress address, String username, String password, ISessionConfig config, ISessionStructureFactory factory) {
158 +
		this(address, Socks5Command.CONNECT, username, password, config, factory);
159 +
	}
160 +
	
161 +
	/**
162 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
163 +
	 * address, SOCKS5 command and the default (10 seconds) connection timeout.
164 +
	 * <p>
165 +
	 * NOTE: The connection timeout will have no effect if the associated session
166 +
	 * does not support a session timer.
167 +
	 * 
168 +
	 * @param address the destination address to the host to which the connection
169 +
	 *                should be proxied
170 +
	 * @param command the SCOCS5 command
171 +
	 * @throws IllegalArgumentException if the address or the command is null
172 +
	 */
173 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command) {
174 +
		this(address, command, null, null, null, null);
175 +
	}
176 +
177 +
	/**
178 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
179 +
	 * address, SOCKS5 command, the default (10 seconds) connection timeout and
180 +
	 * configuration.
181 +
	 * <p>
182 +
	 * NOTE: The connection timeout will have no effect if the associated session
183 +
	 * does not support a session timer.
184 +
	 * 
185 +
	 * @param address the destination address to the host to which the connection
186 +
	 *                should be proxied
187 +
	 * @param command the SCOCS5 command
188 +
	 * @param config  the session configuration object, or {@code null} to use the
189 +
	 *                default configuration
190 +
	 * @throws IllegalArgumentException if the address or the command is null
191 +
	 */
192 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, ISessionConfig config) {
193 +
		this(address, command, null, null, config, null);
194 +
	}
195 +
196 +
	/**
197 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
198 +
	 * address, SOCKS5 command, the default (10 seconds) connection timeout,
199 +
	 * configuration and factory.
200 +
	 * <p>
201 +
	 * NOTE: The connection timeout will have no effect if the associated session
202 +
	 * does not support a session timer.
203 +
	 * 
204 +
	 * @param address the destination address to the host to which the connection
205 +
	 *                should be proxied
206 +
	 * @param command the SCOCS5 command
207 +
	 * @param config  the session configuration object, or {@code null} to use the
208 +
	 *                default configuration
209 +
	 * @param factory the factory that will be used to configure the internal
210 +
	 *                structure of the associated session, or {@code null} to use
211 +
	 *                the default factory
212 +
	 * @throws IllegalArgumentException if the address or the command is null
213 +
	 */
214 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, ISessionConfig config, ISessionStructureFactory factory) {
215 +
		this(address, command, null, null, config, factory);
216 +
	}
217 +
	
218 +
	/**
219 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
220 +
	 * address, SOCKS5 command, user's name/password and the default (10 seconds)
221 +
	 * connection timeout.
222 +
	 * <p>
223 +
	 * NOTE: The connection timeout will have no effect if the associated session
224 +
	 * does not support a session timer.
225 +
	 * 
226 +
	 * @param address  the destination address to the host to which the connection
227 +
	 *                 should be proxied
228 +
	 * @param command  the SCOCS5 command
229 +
	 * @param username the user's name, or {@code null} for an empty name
230 +
	 * @param password the user's password, or {@code null} for an empty password
231 +
	 * @throws IllegalArgumentException if the address or the command is null
232 +
	 */
233 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, String username, String password) {
234 +
		this(address, command, username, password, null, null);
235 +
	}
236 +
237 +
	/**
238 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
239 +
	 * address, SOCKS5 command, user's name/password, the default (10 seconds)
240 +
	 * connection timeout and configuration.
241 +
	 * <p>
242 +
	 * NOTE: The connection timeout will have no effect if the associated session
243 +
	 * does not support a session timer.
244 +
	 * 
245 +
	 * @param address  the destination address to the host to which the connection
246 +
	 *                 should be proxied
247 +
	 * @param command  the SCOCS5 command
248 +
	 * @param username the user's name, or {@code null} for an empty name
249 +
	 * @param password the user's password, or {@code null} for an empty password
250 +
	 * @param config   the session configuration object, or {@code null} to use the
251 +
	 *                 default configuration
252 +
	 * @throws IllegalArgumentException if the address or the command is null
253 +
	 */
254 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, String username, String password, ISessionConfig config) {
255 +
		this(address, command, username, password, config, null);
256 +
	}
257 +
	
258 +
	/**
259 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
260 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command and
261 +
	 * connection timeout.
262 +
	 * <p>
263 +
	 * NOTE: The connection timeout will have no effect if the associated session
264 +
	 * does not support a session timer.
265 +
	 * 
266 +
	 * @param address           the destination address to the host to which the
267 +
	 *                          connection should be proxied
268 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
269 +
	 *                          or {@code 0} to wait an infinite amount of time for
270 +
	 *                          establishing of the SOCKS5 connection.
271 +
	 * @throws IllegalArgumentException if the address is null
272 +
	 */
273 +
	public Socks5ProxyHandler(InetSocketAddress address, long connectionTimeout) {
274 +
		this(address, Socks5Command.CONNECT, null, null, connectionTimeout, null, null);
275 +
	}
276 +
	
277 +
	/**
278 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
279 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command,
280 +
	 * connection timeout and configuration.
281 +
	 * <p>
282 +
	 * NOTE: The connection timeout will have no effect if the associated session
283 +
	 * does not support a session timer.
284 +
	 * 
285 +
	 * @param address           the destination address to the host to which the
286 +
	 *                          connection should be proxied
287 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
288 +
	 *                          or {@code 0} to wait an infinite amount of time for
289 +
	 *                          establishing of the SOCKS5 connection.
290 +
	 * @param config            the session configuration object, or {@code null} to
291 +
	 *                          use the default configuration
292 +
	 * @throws IllegalArgumentException if the address is null
293 +
	 */
294 +
	public Socks5ProxyHandler(InetSocketAddress address, long connectionTimeout, ISessionConfig config) {
295 +
		this(address, Socks5Command.CONNECT, null, null, connectionTimeout, config, null);
296 +
	}
297 +
298 +
	/**
299 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
300 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command,
301 +
	 * connection timeout, configuration and factory.
302 +
	 * <p>
303 +
	 * NOTE: The connection timeout will have no effect if the associated session
304 +
	 * does not support a session timer.
305 +
	 * 
306 +
	 * @param address           the destination address to the host to which the
307 +
	 *                          connection should be proxied
308 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
309 +
	 *                          or {@code 0} to wait an infinite amount of time for
310 +
	 *                          establishing of the SOCKS5 connection.
311 +
	 * @param config            the session configuration object, or {@code null} to
312 +
	 *                          use the default configuration
313 +
	 * @param factory           the factory that will be used to configure the
314 +
	 *                          internal structure of the associated session, or
315 +
	 *                          {@code null} to use the default factory
316 +
	 * @throws IllegalArgumentException if the address is null
317 +
	 */
318 +
	public Socks5ProxyHandler(InetSocketAddress address, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
319 +
		this(address, Socks5Command.CONNECT, null, null, connectionTimeout, config, factory);
320 +
	}
321 +
322 +
	/**
323 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
324 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, user's
325 +
	 * name/password and connection timeout.
326 +
	 * <p>
327 +
	 * NOTE: The connection timeout will have no effect if the associated session
328 +
	 * does not support a session timer.
329 +
	 * 
330 +
	 * @param address           the destination address to the host to which the
331 +
	 *                          connection should be proxied
332 +
	 * @param username          the user's name, or {@code null} for an empty name
333 +
	 * @param password          the user's password, or {@code null} for an empty
334 +
	 *                          password
335 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
336 +
	 *                          or {@code 0} to wait an infinite amount of time for
337 +
	 *                          establishing of the SOCKS5 connection.
338 +
	 * @throws IllegalArgumentException if the address is null
339 +
	 */
340 +
	public Socks5ProxyHandler(InetSocketAddress address, String username, String password, long connectionTimeout) {
341 +
		this(address, Socks5Command.CONNECT, username, password, connectionTimeout, null, null);
342 +
	}
343 +
344 +
	/**
345 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
346 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, user's
347 +
	 * name/password, connection timeout and configuration.
348 +
	 * <p>
349 +
	 * NOTE: The connection timeout will have no effect if the associated session
350 +
	 * does not support a session timer.
351 +
	 * 
352 +
	 * @param address           the destination address to the host to which the
353 +
	 *                          connection should be proxied
354 +
	 * @param username          the user's name, or {@code null} for an empty name
355 +
	 * @param password          the user's password, or {@code null} for an empty
356 +
	 *                          password
357 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
358 +
	 *                          or {@code 0} to wait an infinite amount of time for
359 +
	 *                          establishing of the SOCKS5 connection.
360 +
	 * @param config            the session configuration object, or {@code null} to
361 +
	 *                          use the default configuration
362 +
	 * @throws IllegalArgumentException if the address is null
363 +
	 */
364 +
	public Socks5ProxyHandler(InetSocketAddress address, String username, String password, long connectionTimeout, ISessionConfig config) {
365 +
		this(address, Socks5Command.CONNECT, username, password, connectionTimeout, config, null);
366 +
	}
367 +
368 +
	/**
369 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
370 +
	 * address, the default ({@link Socks5Command#CONNECT CONNECT}) command, user's
371 +
	 * name/password, connection timeout, configuration and factory.
372 +
	 * <p>
373 +
	 * NOTE: The connection timeout will have no effect if the associated session
374 +
	 * does not support a session timer.
375 +
	 * 
376 +
	 * @param address           the destination address to the host to which the
377 +
	 *                          connection should be proxied
378 +
	 * @param username          the user's name, or {@code null} for an empty name
379 +
	 * @param password          the user's password, or {@code null} for an empty
380 +
	 *                          password
381 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
382 +
	 *                          or {@code 0} to wait an infinite amount of time for
383 +
	 *                          establishing of the SOCKS5 connection.
384 +
	 * @param config            the session configuration object, or {@code null} to
385 +
	 *                          use the default configuration
386 +
	 * @param factory           the factory that will be used to configure the
387 +
	 *                          internal structure of the associated session, or
388 +
	 *                          {@code null} to use the default factory
389 +
	 * @throws IllegalArgumentException if the address is null
390 +
	 */
391 +
	public Socks5ProxyHandler(InetSocketAddress address, String username, String password, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
392 +
		this(address, Socks5Command.CONNECT, username, password, connectionTimeout, config, factory);
393 +
	}
394 +
	
395 +
	/**
396 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
397 +
	 * address, SOCKS5 command and connection timeout.
398 +
	 * <p>
399 +
	 * NOTE: The connection timeout will have no effect if the associated session
400 +
	 * does not support a session timer.
401 +
	 * 
402 +
	 * @param address           the destination address to the host to which the
403 +
	 *                          connection should be proxied
404 +
	 * @param command           the SCOCS5 command
405 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
406 +
	 *                          or {@code 0} to wait an infinite amount of time for
407 +
	 *                          establishing of the SOCKS5 connection.
408 +
	 * @throws IllegalArgumentException if the address or the command is null
409 +
	 */
410 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, long connectionTimeout) {
411 +
		this(address, command, null, null, connectionTimeout, null, null);
412 +
	}
413 +
414 +
	/**
415 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
416 +
	 * address, SOCKS5 command, connection timeout and configuration.
417 +
	 * <p>
418 +
	 * NOTE: The connection timeout will have no effect if the associated session
419 +
	 * does not support a session timer.
420 +
	 * 
421 +
	 * @param address           the destination address to the host to which the
422 +
	 *                          connection should be proxied
423 +
	 * @param command           the SCOCS5 command
424 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
425 +
	 *                          or {@code 0} to wait an infinite amount of time for
426 +
	 *                          establishing of the SOCKS5 connection.
427 +
	 * @param config            the session configuration object, or {@code null} to
428 +
	 *                          use the default configuration
429 +
	 * @throws IllegalArgumentException if the address or the command is null
430 +
	 */
431 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, long connectionTimeout, ISessionConfig config) {
432 +
		this(address, command, null, null, connectionTimeout, config, null);
433 +
	}
434 +
435 +
	/**
436 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
437 +
	 * address, SOCKS5 command, connection timeout, configuration and factory.
438 +
	 * <p>
439 +
	 * NOTE: The connection timeout will have no effect if the associated session
440 +
	 * does not support a session timer.
441 +
	 * 
442 +
	 * @param address           the destination address to the host to which the
443 +
	 *                          connection should be proxied
444 +
	 * @param command           the SCOCS5 command
445 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
446 +
	 *                          or {@code 0} to wait an infinite amount of time for
447 +
	 *                          establishing of the SOCKS5 connection.
448 +
	 * @param config            the session configuration object, or {@code null} to
449 +
	 *                          use the default configuration
450 +
	 * @param factory           the factory that will be used to configure the
451 +
	 *                          internal structure of the associated session, or
452 +
	 *                          {@code null} to use the default factory
453 +
	 * @throws IllegalArgumentException if the address or the command is null
454 +
	 */
455 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
456 +
		this(address, command, null, null, connectionTimeout, config, factory);
457 +
	}
458 +
459 +
	/**
460 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
461 +
	 * address, SOCKS5 command, user's name/password and connection timeout.
462 +
	 * <p>
463 +
	 * NOTE: The connection timeout will have no effect if the associated session
464 +
	 * does not support a session timer.
465 +
	 * 
466 +
	 * @param address           the destination address to the host to which the
467 +
	 *                          connection should be proxied
468 +
	 * @param command           the SCOCS5 command
469 +
	 * @param username			the user's name, or {@code null} for an empty name
470 +
	 * @param password			the user's password, or {@code null} for an empty password
471 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
472 +
	 *                          or {@code 0} to wait an infinite amount of time for
473 +
	 *                          establishing of the SOCKS5 connection.
474 +
	 * @throws IllegalArgumentException if the address or the command is null
475 +
	 */
476 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, String username, String password, long connectionTimeout) {
477 +
		this(address, command, username, password, connectionTimeout, null, null);
478 +
	}
479 +
	
480 +
	/**
481 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
482 +
	 * address, SOCKS5 command, user's name/password, connection timeout and 
483 +
	 * configuration.
484 +
	 * <p>
485 +
	 * NOTE: The connection timeout will have no effect if the associated session
486 +
	 * does not support a session timer.
487 +
	 * 
488 +
	 * @param address           the destination address to the host to which the
489 +
	 *                          connection should be proxied
490 +
	 * @param command           the SCOCS5 command
491 +
	 * @param username			the user's name, or {@code null} for an empty name
492 +
	 * @param password			the user's password, or {@code null} for an empty password
493 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
494 +
	 *                          or {@code 0} to wait an infinite amount of time for
495 +
	 *                          establishing of the SOCKS5 connection.
496 +
	 * @param config            the session configuration object, or {@code null} to
497 +
	 *                          use the default configuration
498 +
	 * @throws IllegalArgumentException if the address or the command is null
499 +
	 */
500 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, String username, String password, long connectionTimeout, ISessionConfig config) {
501 +
		this(address, command, username, password, connectionTimeout, config, null);
502 +
	}
503 +
504 +
	/**
505 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
506 +
	 * address, SOCKS5 command, user's name/password, the default (10 seconds)
507 +
	 * connection timeout, configuration and factory.
508 +
	 * <p>
509 +
	 * NOTE: The connection timeout will have no effect if the associated session
510 +
	 * does not support a session timer.
511 +
	 * 
512 +
	 * @param address  the destination address to the host to which the connection
513 +
	 *                 should be proxied
514 +
	 * @param command  the SCOCS5 command
515 +
	 * @param username the user's name, or {@code null} for an empty name
516 +
	 * @param password the user's password, or {@code null} for an empty password
517 +
	 * @param config   the session configuration object, or {@code null} to use the
518 +
	 *                 default configuration
519 +
	 * @param factory  the factory that will be used to configure the internal
520 +
	 *                 structure of the associated session, or {@code null} to use
521 +
	 *                 the default factory
522 +
	 * @throws IllegalArgumentException if the address or the command is null
523 +
	 */
524 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, String username, String password, ISessionConfig config, ISessionStructureFactory factory) {
525 +
		super(address, config, factory);
526 +
		checkNull(command, "command");
527 +
		commandState = new Socks5CommandState(this, command);
528 +
		passwordAuthState = new Socks5PasswordAuthState(this, username, password, commandState);
529 +
		state = state();
530 +
	}
531 +
	
532 +
	/**
533 +
	 * Constructs a SOCKS5 proxy connection handler with the specified destination
534 +
	 * address, SOCKS5 command, user's name/password, connection timeout, configuration and
535 +
	 * factory.
536 +
	 * <p>
537 +
	 * NOTE: The connection timeout will have no effect if the associated session
538 +
	 * does not support a session timer.
539 +
	 * 
540 +
	 * @param address           the destination address to the host to which the
541 +
	 *                          connection should be proxied
542 +
	 * @param command           the SCOCS5 command
543 +
	 * @param username			the user's name, or {@code null} for an empty name
544 +
	 * @param password			the user's password, or {@code null} for an empty password
545 +
	 * @param connectionTimeout the SOCKS5 proxy connection timeout in milliseconds,
546 +
	 *                          or {@code 0} to wait an infinite amount of time for
547 +
	 *                          establishing of the SOCKS5 connection.
548 +
	 * @param config            the session configuration object, or {@code null} to
549 +
	 *                          use the default configuration
550 +
	 * @param factory           the factory that will be used to configure the
551 +
	 *                          internal structure of the associated session, or
552 +
	 *                          {@code null} to use the default factory
553 +
	 * @throws IllegalArgumentException if the address or the command is null
554 +
	 */
555 +
	public Socks5ProxyHandler(InetSocketAddress address, Socks5Command command, String username, String password, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
556 +
		super(address, connectionTimeout, config, factory);
557 +
		checkNull(command, "command");
558 +
		commandState = new Socks5CommandState(this, command);
559 +
		passwordAuthState = new Socks5PasswordAuthState(this, username, password, commandState);
560 +
		state = state();
561 +
	}
562 +
563 +
	private Socks5InitState state() {
564 +
		AbstractSocksState[] nextStates;
565 +
		Socks5AuthMethod[] authMethods;
566 +
		
567 +
		if (passwordAuthState.isConfigured()) {
568 +
			authMethods = new Socks5AuthMethod[] { Socks5AuthMethod.NO_AUTH, Socks5AuthMethod.PASSWORD };
569 +
			nextStates = new AbstractSocksState[] { commandState, passwordAuthState };
570 +
		}
571 +
		else {
572 +
			authMethods = new Socks5AuthMethod[] { Socks5AuthMethod.NO_AUTH };
573 +
			nextStates = new AbstractSocksState[] { commandState };
574 +
		}
575 +
		return new Socks5InitState(this, authMethods, nextStates);
576 +
	}
577 +
	
578 +
	@Override
579 +
	String protocol() {
580 +
		return ISocks5.PROTOCOL;
581 +
	}
582 +
583 +
}

@@ -0,0 +1,48 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
class SocksDoneState extends AbstractSocksState {
29 +
30 +
	SocksDoneState(AbstractSocksProxyHandler handler) {
31 +
		super(handler);
32 +
	}
33 +
34 +
	@Override
35 +
	AbstractSocksState read(byte[] data) {
36 +
		return this;
37 +
	}
38 +
39 +
	@Override
40 +
	void handleReady() {
41 +
	}
42 +
43 +
	@Override
44 +
	int responseSize() {
45 +
		return 0;
46 +
	}
47 +
	
48 +
}

@@ -0,0 +1,302 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.net.InetSocketAddress;
29 +
import org.snf4j.core.factory.ISessionStructureFactory;
30 +
import org.snf4j.core.session.ISessionConfig;
31 +
32 +
/**
33 +
 * Handles client proxy connections via the SOCKS Protocol Version 4.
34 +
 * 
35 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
36 +
 */
37 +
public class Socks4ProxyHandler extends AbstractSocksProxyHandler {
38 +
39 +
	/**
40 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
41 +
	 * address, the default ({@link Socks4Command#CONNECT CONNECT}) command, user's
42 +
	 * name and the default (10 seconds) connection timeout.
43 +
	 * <p>
44 +
	 * NOTE: The connection timeout will have no effect if the associated session
45 +
	 * does not support a session timer.
46 +
	 * 
47 +
	 * @param address           the destination address to the host to which the
48 +
	 *                          connection should be proxied
49 +
	 * @param username          the user's name, or {@code null} for an empty name
50 +
	 * @throws IllegalArgumentException if the address is null
51 +
	 */
52 +
	public Socks4ProxyHandler(InetSocketAddress address, String username) {
53 +
		this(address, Socks4Command.CONNECT, username, null, null);
54 +
	}
55 +
56 +
	/**
57 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
58 +
	 * address, the default ({@link Socks4Command#CONNECT CONNECT}) command, user's
59 +
	 * name, the default (10 seconds) connection timeout and configuration.
60 +
	 * <p>
61 +
	 * NOTE: The connection timeout will have no effect if the associated session
62 +
	 * does not support a session timer.
63 +
	 * 
64 +
	 * @param address           the destination address to the host to which the
65 +
	 *                          connection should be proxied
66 +
	 * @param username          the user's name, or {@code null} for an empty name
67 +
	 * @param config            the session configuration object, or {@code null} to
68 +
	 *                          use the default configuration
69 +
	 * @throws IllegalArgumentException if the address is null
70 +
	 */
71 +
	public Socks4ProxyHandler(InetSocketAddress address, String username, ISessionConfig config) {
72 +
		this(address, Socks4Command.CONNECT, username, config, null);
73 +
	}
74 +
75 +
	/**
76 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
77 +
	 * address, the default ({@link Socks4Command#CONNECT CONNECT}) command, user's
78 +
	 * name, the default (10 seconds) connection timeout, configuration and factory.
79 +
	 * <p>
80 +
	 * NOTE: The connection timeout will have no effect if the associated session
81 +
	 * does not support a session timer.
82 +
	 * 
83 +
	 * @param address           the destination address to the host to which the
84 +
	 *                          connection should be proxied
85 +
	 * @param username          the user's name, or {@code null} for an empty name
86 +
	 * @param config            the session configuration object, or {@code null} to
87 +
	 *                          use the default configuration
88 +
	 * @param factory           the factory that will be used to configure the
89 +
	 *                          internal structure of the associated session, or
90 +
	 *                          {@code null} to use the default factory
91 +
	 * @throws IllegalArgumentException if the address is null
92 +
	 */
93 +
	public Socks4ProxyHandler(InetSocketAddress address, String username, ISessionConfig config, ISessionStructureFactory factory) {
94 +
		this(address, Socks4Command.CONNECT, username, config, factory);
95 +
	}
96 +
	
97 +
	/**
98 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
99 +
	 * address, SOCKS4 command, user's name and the default (10 seconds) connection
100 +
	 * timeout.
101 +
	 * <p>
102 +
	 * NOTE: The connection timeout will have no effect if the associated session
103 +
	 * does not support a session timer.
104 +
	 * 
105 +
	 * @param address  the destination address to the host to which the connection
106 +
	 *                 should be proxied
107 +
	 * @param command  the SCOCS4 command
108 +
	 * @param username the user's name, or {@code null} for an empty name
109 +
	 * @throws IllegalArgumentException if the address or the command is null
110 +
	 */
111 +
	public Socks4ProxyHandler(InetSocketAddress address, Socks4Command command, String username) {
112 +
		this(address, command, username, null, null);
113 +
	}
114 +
115 +
	/**
116 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
117 +
	 * address, SOCKS4 command, user's name, the default (10 seconds) connection
118 +
	 * timeout and configuration.
119 +
	 * <p>
120 +
	 * NOTE: The connection timeout will have no effect if the associated session
121 +
	 * does not support a session timer.
122 +
	 * 
123 +
	 * @param address  the destination address to the host to which the connection
124 +
	 *                 should be proxied
125 +
	 * @param command  the SCOCS4 command
126 +
	 * @param username the user's name, or {@code null} for an empty name
127 +
	 * @param config   the session configuration object, or {@code null} to use the
128 +
	 *                 default configuration
129 +
	 * @throws IllegalArgumentException if the address or the command is null
130 +
	 */
131 +
	public Socks4ProxyHandler(InetSocketAddress address, Socks4Command command, String username, ISessionConfig config) {
132 +
		this(address, command, username, config, null);
133 +
	}
134 +
	
135 +
	/**
136 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
137 +
	 * address, the default ({@link Socks4Command#CONNECT CONNECT}) command, user's
138 +
	 * name and connection timeout.
139 +
	 * <p>
140 +
	 * NOTE: The connection timeout will have no effect if the associated session
141 +
	 * does not support a session timer.
142 +
	 * 
143 +
	 * @param address           the destination address to the host to which the
144 +
	 *                          connection should be proxied
145 +
	 * @param username          the user's name, or {@code null} for an empty name
146 +
	 * @param connectionTimeout the SOCKS4 proxy connection timeout in milliseconds,
147 +
	 *                          or {@code 0} to wait an infinite amount of time for
148 +
	 *                          establishing of the SOCKS4 connection.
149 +
	 * @throws IllegalArgumentException if the address is null
150 +
	 */
151 +
	public Socks4ProxyHandler(InetSocketAddress address, String username, long connectionTimeout) {
152 +
		this(address, Socks4Command.CONNECT, username, connectionTimeout, null, null);
153 +
	}
154 +
155 +
	/**
156 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
157 +
	 * address, the default ({@link Socks4Command#CONNECT CONNECT}) command, user's
158 +
	 * name, connection timeout and configuration.
159 +
	 * <p>
160 +
	 * NOTE: The connection timeout will have no effect if the associated session
161 +
	 * does not support a session timer.
162 +
	 * 
163 +
	 * @param address           the destination address to the host to which the
164 +
	 *                          connection should be proxied
165 +
	 * @param username          the user's name, or {@code null} for an empty name
166 +
	 * @param connectionTimeout the SOCKS4 proxy connection timeout in milliseconds,
167 +
	 *                          or {@code 0} to wait an infinite amount of time for
168 +
	 *                          establishing of the SOCKS4 connection.
169 +
	 * @param config            the session configuration object, or {@code null} to
170 +
	 *                          use the default configuration
171 +
	 * @throws IllegalArgumentException if the address is null
172 +
	 */
173 +
	public Socks4ProxyHandler(InetSocketAddress address, String username, long connectionTimeout, ISessionConfig config) {
174 +
		this(address, Socks4Command.CONNECT, username, connectionTimeout, config, null);
175 +
	}
176 +
	
177 +
	/**
178 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
179 +
	 * address, the default ({@link Socks4Command#CONNECT CONNECT}) command, user's
180 +
	 * name, connection timeout, configuration and factory.
181 +
	 * <p>
182 +
	 * NOTE: The connection timeout will have no effect if the associated session
183 +
	 * does not support a session timer.
184 +
	 * 
185 +
	 * @param address           the destination address to the host to which the
186 +
	 *                          connection should be proxied
187 +
	 * @param username          the user's name, or {@code null} for an empty name
188 +
	 * @param connectionTimeout the SOCKS4 proxy connection timeout in milliseconds,
189 +
	 *                          or {@code 0} to wait an infinite amount of time for
190 +
	 *                          establishing of the SOCKS4 connection.
191 +
	 * @param config            the session configuration object, or {@code null} to
192 +
	 *                          use the default configuration
193 +
	 * @param factory           the factory that will be used to configure the
194 +
	 *                          internal structure of the associated session, or
195 +
	 *                          {@code null} to use the default factory
196 +
	 * @throws IllegalArgumentException if the address is null
197 +
	 */
198 +
	public Socks4ProxyHandler(InetSocketAddress address, String username, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
199 +
		this(address, Socks4Command.CONNECT, username, connectionTimeout, config, factory);
200 +
	}
201 +
202 +
	/**
203 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
204 +
	 * address, SOCKS4 command, user's name and connection timeout.
205 +
	 * <p>
206 +
	 * NOTE: The connection timeout will have no effect if the associated session
207 +
	 * does not support a session timer.
208 +
	 * 
209 +
	 * @param address           the destination address to the host to which the
210 +
	 *                          connection should be proxied
211 +
	 * @param command           the SCOCS4 command
212 +
	 * @param username			the user's name, or {@code null} for an empty name
213 +
	 * @param connectionTimeout the SOCKS4 proxy connection timeout in milliseconds,
214 +
	 *                          or {@code 0} to wait an infinite amount of time for
215 +
	 *                          establishing of the SOCKS4 connection.
216 +
	 * @throws IllegalArgumentException if the address or the command is null
217 +
	 */
218 +
	public Socks4ProxyHandler(InetSocketAddress address, Socks4Command command, String username, long connectionTimeout) {
219 +
		this(address, command, username, connectionTimeout, null, null);
220 +
	}
221 +
222 +
	/**
223 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
224 +
	 * address, SOCKS4 command, user's name, connection timeout and configuration.
225 +
	 * <p>
226 +
	 * NOTE: The connection timeout will have no effect if the associated session
227 +
	 * does not support a session timer.
228 +
	 * 
229 +
	 * @param address           the destination address to the host to which the
230 +
	 *                          connection should be proxied
231 +
	 * @param command           the SCOCS4 command
232 +
	 * @param username			the user's name, or {@code null} for an empty name
233 +
	 * @param connectionTimeout the SOCKS4 proxy connection timeout in milliseconds,
234 +
	 *                          or {@code 0} to wait an infinite amount of time for
235 +
	 *                          establishing of the SOCKS4 connection.
236 +
	 * @param config            the session configuration object, or {@code null} to
237 +
	 *                          use the default configuration
238 +
	 * @throws IllegalArgumentException if the address or the command is null
239 +
	 */
240 +
	public Socks4ProxyHandler(InetSocketAddress address, Socks4Command command, String username, long connectionTimeout, ISessionConfig config) {
241 +
		this(address, command, username, connectionTimeout, config, null);
242 +
	}
243 +
	
244 +
	/**
245 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
246 +
	 * address, SOCKS4 command, user's name, the default (10 seconds) connection
247 +
	 * timeout, configuration and factory.
248 +
	 * <p>
249 +
	 * NOTE: The connection timeout will have no effect if the associated session
250 +
	 * does not support a session timer.
251 +
	 * 
252 +
	 * @param address  the destination address to the host to which the connection
253 +
	 *                 should be proxied
254 +
	 * @param command  the SCOCS4 command
255 +
	 * @param username the user's name, or {@code null} for an empty name
256 +
	 * @param config   the session configuration object, or {@code null} to use the
257 +
	 *                 default configuration
258 +
	 * @param factory  the factory that will be used to configure the internal
259 +
	 *                 structure of the associated session, or {@code null} to use
260 +
	 *                 the default factory
261 +
	 * @throws IllegalArgumentException if the address or the command is null
262 +
	 */
263 +
	public Socks4ProxyHandler(InetSocketAddress address, Socks4Command command, String username, ISessionConfig config, ISessionStructureFactory factory) {
264 +
		super(address, config, factory);
265 +
		checkNull(command, "command");
266 +
		state = new Socks4CommandState(this, command, username);
267 +
	}
268 +
	
269 +
	/**
270 +
	 * Constructs a SOCKS4 proxy connection handler with the specified destination
271 +
	 * address, SOCKS4 command, user's name, connection timeout, configuration and
272 +
	 * factory.
273 +
	 * <p>
274 +
	 * NOTE: The connection timeout will have no effect if the associated session
275 +
	 * does not support a session timer.
276 +
	 * 
277 +
	 * @param address           the destination address to the host to which the
278 +
	 *                          connection should be proxied
279 +
	 * @param command           the SCOCS4 command
280 +
	 * @param username			the user's name, or {@code null} for an empty name
281 +
	 * @param connectionTimeout the SOCKS4 proxy connection timeout in milliseconds,
282 +
	 *                          or {@code 0} to wait an infinite amount of time for
283 +
	 *                          establishing of the SOCKS4 connection.
284 +
	 * @param config            the session configuration object, or {@code null} to
285 +
	 *                          use the default configuration
286 +
	 * @param factory           the factory that will be used to configure the
287 +
	 *                          internal structure of the associated session, or
288 +
	 *                          {@code null} to use the default factory
289 +
	 * @throws IllegalArgumentException if the address or the command is null
290 +
	 */
291 +
	public Socks4ProxyHandler(InetSocketAddress address, Socks4Command command, String username, long connectionTimeout, ISessionConfig config, ISessionStructureFactory factory) {
292 +
		super(address, connectionTimeout, config, factory);
293 +
		checkNull(command, "command");
294 +
		state = new Socks4CommandState(this, command, username);
295 +
	}
296 +
297 +
	@Override
298 +
	String protocol() {
299 +
		return ISocks4.PROTOCOL;
300 +
	}
301 +
302 +
}

@@ -0,0 +1,72 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
class Socks4Reply implements ISocksReply {
29 +
30 +
	private final int status;
31 +
	
32 +
	private final String address;
33 +
	
34 +
	private final int port;
35 +
	
36 +
	Socks4Reply(int status, String address, int port) {
37 +
		this.status = status;
38 +
		this.address = address;
39 +
		this.port = port;
40 +
	}
41 +
	
42 +
	@Override
43 +
	public boolean isSuccessful() {
44 +
		return status == Socks4Status.SUCCESS.code();
45 +
	}
46 +
47 +
	@Override
48 +
	public int getStatus() {
49 +
		return status;
50 +
	}
51 +
52 +
	@Override
53 +
	public String getStatusDescription() {
54 +
		return Socks4Status.valueOf(status).description();
55 +
	}
56 +
57 +
	@Override
58 +
	public int getPort() {
59 +
		return port;
60 +
	}
61 +
62 +
	@Override
63 +
	public String getAddress() {
64 +
		return address;
65 +
	}
66 +
67 +
	@Override
68 +
	public SocksAddressType getAddressType() {
69 +
		return SocksAddressType.IPV4;
70 +
	}
71 +
72 +
}

@@ -0,0 +1,59 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.nio.ByteBuffer;
29 +
30 +
abstract class AbstractSocksState {
31 +
	
32 +
	final static byte VER_INDEX = 0;
33 +
	
34 +
	protected final AbstractSocksProxyHandler handler;
35 +
	
36 +
	AbstractSocksState(AbstractSocksProxyHandler handler) {
37 +
		this.handler = handler;
38 +
	}
39 +
	
40 +
	protected int length(ByteBuffer data, boolean flipped) {
41 +
		return flipped ? data.remaining() : data.position();
42 +
	}
43 +
	
44 +
	int available(ByteBuffer data, boolean flipped) {
45 +
		return available(null, 0, length(data, flipped));
46 +
	}
47 +
48 +
	int available(byte[] data, int off, int len) {
49 +
		int size = responseSize();
50 +
		
51 +
		return len < size ? 0 : size;
52 +
	}
53 +
	
54 +
	abstract int responseSize();
55 +
	
56 +
	abstract AbstractSocksState read(byte[] data);
57 +
	
58 +
	abstract void handleReady();
59 +
}

@@ -0,0 +1,101 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.nio.ByteBuffer;
29 +
import java.nio.charset.StandardCharsets;
30 +
31 +
class Socks5PasswordAuthState extends AbstractSocksState {
32 +
	
33 +
	private final static byte VERSION = 1;	
34 +
	
35 +
	private final static byte SUCCESS = 0;
36 +
	
37 +
	private final static int RESPONSE_SIZE = 2;
38 +
39 +
	final static int STATUS_INDEX = 1;
40 +
	
41 +
	private final String username;
42 +
	
43 +
	private final String password;
44 +
	
45 +
	private final AbstractSocksState nextState;
46 +
47 +
	Socks5PasswordAuthState(Socks5ProxyHandler handler, String username, String password, AbstractSocksState nextState) {
48 +
		super(handler);
49 +
		this.username = check(username, "username");
50 +
		this.password = check(password, "password");
51 +
		this.nextState = nextState;
52 +
	}
53 +
	
54 +
	private String check(String value, String name) {
55 +
		value = value == null || value.isEmpty() ? null : value;
56 +
		if (value != null) {
57 +
			if (value.getBytes(StandardCharsets.US_ASCII).length > 255) {
58 +
				throw new IllegalArgumentException(name + " length is too long (expected less than 256)");
59 +
			}
60 +
		}
61 +
		return value;
62 +
	}
63 +
64 +
	boolean isConfigured() {
65 +
		return username != null || password != null;
66 +
	}
67 +
	
68 +
	@Override
69 +
	int responseSize() {
70 +
		return RESPONSE_SIZE;
71 +
	}
72 +
	
73 +
	@Override
74 +
	AbstractSocksState read(byte[] data) {
75 +
		if (data[VER_INDEX] != VERSION) {
76 +
			throw new ProxyConnectionException("Unsupported SOCKS5 subnegotiation reply version: " + data[0]);
77 +
		}
78 +
		
79 +
		byte statusCode = data[STATUS_INDEX];
80 +
		
81 +
		if (statusCode != SUCCESS) {
82 +
			throw new ProxyConnectionException("Username/Password authentication response status code: " + statusCode);
83 +
		}
84 +
		return nextState;
85 +
	}
86 +
87 +
	@Override
88 +
	void handleReady() {
89 +
		byte[] user = username == null ? new byte[0] : username.getBytes(StandardCharsets.US_ASCII);
90 +
		byte[] pass = password == null ? new byte[0] : password.getBytes(StandardCharsets.US_ASCII);
91 +
		ByteBuffer buf = handler.getSession().allocate(3 + user.length + pass.length);
92 +
93 +
		buf.put(VERSION);
94 +
		buf.put((byte)user.length);
95 +
		buf.put(user);
96 +
		buf.put((byte)pass.length);
97 +
		buf.put(pass);
98 +
		handler.flipAndWrite(buf);
99 +
	}
100 +
101 +
}

@@ -0,0 +1,704 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.util;
27 +
28 +
/**
29 +
 * A class with network-related utility functions.
30 +
 * 
31 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
32 +
 */
33 +
public final class NetworkUtil {
34 +
35 +
	private NetworkUtil() {}
36 +
37 +
	static int digit(char c) {
38 +
		switch (c) {
39 +
		case '0': return 0;
40 +
		case '1': return 1;
41 +
		case '2': return 2;
42 +
		case '3': return 3;
43 +
		case '4': return 4;
44 +
		case '5': return 5;
45 +
		case '6': return 6;
46 +
		case '7': return 7;
47 +
		case '8': return 8;
48 +
		case '9': return 9;
49 +
		}
50 +
		return -1;
51 +
	}
52 +
53 +
	static int hexDigit(char c) {
54 +
		switch (c) {
55 +
		case '0': return 0;
56 +
		case '1': return 1;
57 +
		case '2': return 2;
58 +
		case '3': return 3;
59 +
		case '4': return 4;
60 +
		case '5': return 5;
61 +
		case '6': return 6;
62 +
		case '7': return 7;
63 +
		case '8': return 8;
64 +
		case '9': return 9;
65 +
		}
66 +
		
67 +
		c = Character.toLowerCase(c);
68 +
		switch (c) {
69 +
		case 'a': return 10;
70 +
		case 'b': return 11;
71 +
		case 'c': return 12;
72 +
		case 'd': return 13;
73 +
		case 'e': return 14;
74 +
		case 'f': return 15;
75 +
		}
76 +
		return -1;
77 +
	}
78 +
	
79 +
	/**
80 +
	 * Converts a text representation of an IPv6 address into an array of bytes.
81 +
	 * 
82 +
	 * @param ip     the text representation of an IPv6 address
83 +
	 * @param output an array for the output bytes
84 +
	 * @param off    starting position for the output bytes in the array
85 +
	 * @return {@code true} if the text representation was a valid IPv6 address. If
86 +
	 *         the returned value is {@code false} the initial content in the output
87 +
	 *         array is not changed
88 +
	 */
89 +
	public static boolean ipv6ToBytes(CharSequence ip, byte[] output, int off) {
90 +
		int len = ip.length();
91 +
		int i,j;
92 +
		
93 +
		if (len < 2) {
94 +
			return false;
95 +
		}
96 +
		if (ip.charAt(0) == '[') {
97 +
			if (ip.charAt(len - 1) != ']') {
98 +
				return false;
99 +
			}
100 +
			i = 1;
101 +
			--len; 
102 +
		}
103 +
		else {
104 +
			i = 0;
105 +
		}
106 +
		
107 +
		for (j=i; j<len; ++j) {
108 +
			if (ip.charAt(j) == '%') {
109 +
				len = j;
110 +
				break;
111 +
			}
112 +
		}
113 +
		if (len-i < 2) {
114 +
			return false;
115 +
		}
116 +
117 +
		boolean doubleColon;
118 +
		char c;
119 +
		int colons;
120 +
		
121 +
		if (ip.charAt(i) == ':') {
122 +
			if (ip.charAt(i+1) == ':') {
123 +
				i += 2;
124 +
				doubleColon = true;
125 +
				c = ':';
126 +
				colons = 2;
127 +
			}
128 +
			else {
129 +
				return false;
130 +
			}
131 +
		}
132 +
		else {
133 +
			doubleColon = false;
134 +
			c = 0;
135 +
			colons = 0;
136 +
		}
137 +
		
138 +
		int word = -1, maxWord = 0xffff, periods = 0, radix = 16;
139 +
		int j0 = 0, d;
140 +
		byte[] buf = new byte[16];
141 +
		char prevc;
142 +
		
143 +
		j = 0;
144 +
		for (; i<len; ++i) {
145 +
			prevc = c;
146 +
			c = ip.charAt(i);	
147 +
			switch (c) {
148 +
			case '.':
149 +
				if (periods > 2 || word == -1 || colons == 0) {
150 +
					return false;
151 +
				}
152 +
				if (radix == 16) { 
153 +
					maxWord = 255;
154 +
					radix = 10;
155 +
					if (word > 9) {
156 +
						--i;
157 +
						for (; ip.charAt(i) != ':'; --i);
158 +
						c = ':';
159 +
						word = -1;
160 +
						break;
161 +
					}
162 +
				}
163 +
				if (j > 15) {
164 +
					return false;
165 +
				}
166 +
				else {
167 +
					buf[j++] = (byte)word;
168 +
					word = -1;
169 +
					++periods;
170 +
				}
171 +
				break;
172 +
				
173 +
			case ':':
174 +
				++colons;
175 +
				if (periods > 0) {
176 +
					return false;
177 +
				}
178 +
				if (prevc == ':') {
179 +
					if (doubleColon) {
180 +
						return false;
181 +
					}
182 +
					doubleColon = true;
183 +
					j0 = j;
184 +
				}
185 +
				else if (j > 14) {
186 +
					return false;
187 +
				}
188 +
				else {
189 +
					buf[j++] = (byte)(word >> 8);
190 +
					buf[j++] = (byte)word;
191 +
					word = -1;
192 +
				}
193 +
				break;
194 +
				
195 +
			default:
196 +
				if (radix == 16) {
197 +
					d = hexDigit(c);
198 +
					if (d == -1) {
199 +
						return false;
200 +
					}
201 +
				}
202 +
				else {
203 +
					d = digit(c);
204 +
					if (d == -1) {
205 +
						return false;
206 +
					}
207 +
				}
208 +
				if (word == -1) {
209 +
					word = d;
210 +
				}
211 +
				else {
212 +
					word *= radix;
213 +
					word += d;
214 +
					if (word > maxWord) {
215 +
						return false;
216 +
					}
217 +
				}
218 +
			}
219 +
		}
220 +
		
221 +
		if (periods > 0) {
222 +
			if (periods != 3 || word == -1) {
223 +
				return false;
224 +
			}
225 +
			buf[j++] = (byte)word;
226 +
		}
227 +
		else if (word == -1) {
228 +
			if (ip.charAt(len-2) != ':') {
229 +
				return false;
230 +
			}
231 +
		}
232 +
		else if (j > 14) {
233 +
			return false;
234 +
		}
235 +
		else {
236 +
			buf[j++] = (byte)(word >> 8);
237 +
			buf[j++] = (byte)word;
238 +
		}
239 +
		
240 +
		if (j == 16) {
241 +
			if (doubleColon) {
242 +
				return false;
243 +
			}
244 +
			System.arraycopy(buf, 0, output, off, 16);
245 +
		}
246 +
		else if (doubleColon) {
247 +
			System.arraycopy(buf, 0, output, off, j0);
248 +
			len = 16-j+j0;
249 +
			for (i=j0; i<len; ++i) {
250 +
				output[off+i] = 0;
251 +
			}
252 +
			System.arraycopy(buf, j0, output, off+i, j-j0);
253 +
		}
254 +
		else {
255 +
			return false;
256 +
		}
257 +
		return true;
258 +
	}
259 +
260 +
	/**
261 +
	 * Converts a text representation of an IPv6 address into an array of bytes.
262 +
	 * 
263 +
	 * @param ip the text representation of an IPv6 address
264 +
	 * @return an array of bytes, or {@code null} if the text representation was not
265 +
	 *         a valid IPv6 address
266 +
	 */
267 +
	public static byte[] ipv6ToBytes(CharSequence ip) {
268 +
		byte[] buf = new byte[16];
269 +
		
270 +
		if (ipv6ToBytes(ip,buf,0)) {
271 +
			return buf;
272 +
		}
273 +
		return null;
274 +
	}
275 +
276 +
	/**
277 +
	 * Converts an array of bytes into a compressed text representation of an IPv6
278 +
	 * address.
279 +
	 * 
280 +
	 * @param data      the array of bytes
281 +
	 * @param off       starting position in the array of bytes
282 +
	 * @param embedIpv4 {@code true} if the IPv4 notation should should be embedded
283 +
	 *                  in the returned text representation of the IPv6 address.
284 +
	 * @return the text representation of the IPv6 address
285 +
	 */
286 +
	public static String ipv6ToString(byte[] data, int off, boolean embedIpv4) {
287 +
		return ipv6ToString(data, off, embedIpv4, true);
288 +
	}
289 +
	
290 +
	/**
291 +
	 * Converts an array of bytes into a text representation of an IPv6 address.
292 +
	 * 
293 +
	 * @param data      the array of bytes
294 +
	 * @param off       starting position in the array of bytes
295 +
	 * @param embedIpv4 {@code true} if the IPv4 notation should should be embedded
296 +
	 *                  in the returned text representation of the IPv6 address
297 +
	 * @param compress  {@code true} to used compressed text representation of the
298 +
	 *                  IPv6 address
299 +
	 * 
300 +
	 * @return the text representation of the IPv6 address
301 +
	 */
302 +
	public static String ipv6ToString(byte[] data, int off, boolean embedIpv4, boolean compress) {
303 +
		int[] words = new int[8];
304 +
		int i,j,len = off+16;
305 +
		
306 +
		for (i=off,j=0; i<len; i+=2, ++j) {
307 +
			words[j] = (int)toShort(data, i) & 0xffff;
308 +
		}
309 +
		len = embedIpv4 ? 6 : 8;
310 +
		
311 +
		int p = -1, plen = 0, maxp = -1, maxplen = 0;
312 +
		
313 +
		if (compress) {
314 +
			// Find longest run of 0s
315 +
			for (i=0; i<len; ++i) {
316 +
				if (words[i] == 0) {
317 +
					if (p == -1) {
318 +
						p = i;
319 +
					}
320 +
				}
321 +
				else if (p != -1){
322 +
					plen = i - p;
323 +
					if (plen > maxplen) {
324 +
						maxp = p;
325 +
						maxplen = plen;
326 +
					}
327 +
					p = -1;
328 +
				}
329 +
			}
330 +
			if (p != -1) {
331 +
				plen = i - p;
332 +
				if (plen > maxplen) {
333 +
					maxp = p;
334 +
					maxplen = plen;
335 +
				}
336 +
			}
337 +
			if (maxplen == 1) {
338 +
				maxplen = 0;
339 +
				maxp = -1;
340 +
			}
341 +
			else if (maxp != -1) {
342 +
				j = maxp +maxplen;
343 +
				for (i=maxp; i<j; ++i) {
344 +
					words[i] = -1;
345 +
				}
346 +
			}
347 +
		}
348 +
		
349 +
		//Longest xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd => 6*5+4*4-1
350 +
		StringBuilder sb = new StringBuilder(45);
351 +
		boolean doubleColon = false;
352 +
		
353 +
		for (i=0; i<len; ++i) {
354 +
			j = words[i];
355 +
			if (j == -1) { 
356 +
				if (!doubleColon) {
357 +
					sb.append(i == 0 ? "::" : ":");
358 +
					doubleColon = true;
359 +
				}
360 +
			}
361 +
			else {
362 +
				sb.append(Integer.toHexString(j));
363 +
				if (i < 7) {
364 +
					sb.append(':');
365 +
				}
366 +
			}	
367 +
		}
368 +
		if (embedIpv4) {
369 +
			sb.append((int)data[off+12] & 0xff);
370 +
			sb.append('.');
371 +
			sb.append((int)data[off+13] & 0xff);
372 +
			sb.append('.');
373 +
			sb.append((int)data[off+14] & 0xff);
374 +
			sb.append('.');
375 +
			sb.append((int)data[off+15] & 0xff);
376 +
		}
377 +
		return sb.toString();
378 +
	}
379 +
	
380 +
	/**
381 +
	 * Converts a text representation of an IPv4 address into an array of bytes.
382 +
	 * 
383 +
	 * @param ip     the text representation of an IPv4 address
384 +
	 * @param output an array for the output bytes
385 +
	 * @param off    starting position for the output bytes in the array
386 +
	 * @return {@code true} if the text representation was a valid IPv4 address. If
387 +
	 *         the returned value is {@code false} the initial content in the output
388 +
	 *         array is not changed
389 +
	 */
390 +
	public static boolean ipv4ToBytes(CharSequence ip, byte[] output, int off) {
391 +
		int len = ip.length();
392 +
		
393 +
		if (len >= 7 && len <= 15) {
394 +
			byte[] buf = new byte[3];
395 +
			int periods = 0, octet = -1, d;
396 +
			char c;
397 +
398 +
			for (int i=0; i<len; ++i) {
399 +
				c = ip.charAt(i);
400 +
				if (c == '.') {
401 +
					if (periods > 2 || octet == -1 || octet > 255) {
402 +
						return false;
403 +
					}
404 +
					buf[periods] = (byte)octet;
405 +
					octet = -1;
406 +
					++periods;
407 +
				}
408 +
				else if ((d = digit(c)) == -1) {
409 +
					return false;
410 +
				}
411 +
				else if (octet == -1) {
412 +
					octet = d;
413 +
				}
414 +
				else {
415 +
					octet *= 10;
416 +
					octet += d;
417 +
				}
418 +
			}
419 +
			if (periods == 3 && octet != -1 && octet <= 255) {
420 +
				output[off] = buf[0];
421 +
				output[off+1] = buf[1];
422 +
				output[off+2] = buf[2];
423 +
				output[off+3] = (byte)octet;
424 +
				return true;
425 +
			}
426 +
		}		
427 +
		return false;
428 +
	}
429 +
430 +
	/**
431 +
	 * Converts a text representation of an IPv4 address into an array of bytes.
432 +
	 * 
433 +
	 * @param ip the text representation of an IPv4 address
434 +
	 * @return an array of bytes, or {@code null} if the text representation was not
435 +
	 *         a valid IPv4 address
436 +
	 */
437 +
	public static byte[] ipv4ToBytes(CharSequence ip) {
438 +
		byte[] buf = new byte[4];
439 +
		
440 +
		if (ipv4ToBytes(ip,buf,0)) {
441 +
			return buf;
442 +
		}
443 +
		return null;
444 +
	}
445 +
	
446 +
	/**
447 +
	 * Converts an array of bytes into a text representation of an IPv4 address.
448 +
	 * 
449 +
	 * @param data the array of bytes
450 +
	 * @param off  starting position in the array of bytes
451 +
	 * @return the text representation of the IPv4 address
452 +
	 */
453 +
	public static String ipv4ToString(byte[] data, int off) {
454 +
		StringBuilder ip = new StringBuilder(15);
455 +
		
456 +
		ip.append((int)data[off] & 0xff);
457 +
		ip.append('.');
458 +
		ip.append((int)data[off+1] & 0xff);
459 +
		ip.append('.');
460 +
		ip.append((int)data[off+2] & 0xff);
461 +
		ip.append('.');
462 +
		ip.append((int)data[off+3] & 0xff);
463 +
		return ip.toString();
464 +
	}
465 +
466 +
	/**
467 +
	 * Converts an array of bytes into a text representation of an IPv4 address.
468 +
	 * 
469 +
	 * @param data the array of bytes
470 +
	 * @return the text representation of the IPv4 address
471 +
	 */
472 +
	public static String ipv4ToString(byte[] data) {
473 +
		return ipv4ToString(data, 0);
474 +
	}
475 +
476 +
	/**
477 +
	 * Converts an {@code int} value into a text representation of an IPv4 address.
478 +
	 * 
479 +
	 * @param value the {@code int} value
480 +
	 * @return the text representation of the IPv4 address
481 +
	 */
482 +
	public static String ipv4ToString(int value) {
483 +
		return ipv4ToString(toBytes(value));
484 +
	}
485 +
	
486 +
	/**
487 +
	 * Converts a text representation of an IPv4 address into an {@code int} value.
488 +
	 * 
489 +
	 * @param ip the text representation of an IPv4 address
490 +
	 * @return an {@code int} value
491 +
	 */
492 +
	public static int ipv4ToInt(CharSequence ip) {
493 +
		byte[] buf = ipv4ToBytes(ip);
494 +
		
495 +
		if (buf != null) {
496 +
			return toInt(buf);
497 +
		}
498 +
		throw new IllegalArgumentException("ip is invalid IPv4 address");
499 +
	}
500 +
	
501 +
	/**
502 +
	 * Converts an array of bytes into a port number.
503 +
	 * 
504 +
	 * @param data the array of bytes
505 +
	 * @param off  starting position in the array of bytes
506 +
	 * @return the port number
507 +
	 */
508 +
	public static int toPort(byte[] data, int off) {
509 +
		return (int)toShort(data, off) & 0xffff; 
510 +
	}
511 +
512 +
	/**
513 +
	 * Converts an array of bytes into a port number.
514 +
	 * 
515 +
	 * @param data the array of bytes
516 +
	 * @return the port number
517 +
	 */
518 +
	public static int toPort(byte[] data) {
519 +
		return toPort(data, 0); 
520 +
	}
521 +
522 +
	/**
523 +
	 * Converts a port number into an array of bytes.
524 +
	 * 
525 +
	 * @param port  the port number
526 +
	 * @param output an array for the output bytes
527 +
	 * @param off    starting position for the output bytes in the array
528 +
	 */
529 +
	public static void portToBytes(int port, byte[] output, int off) {
530 +
		output[off] = (byte)(port >> 8);
531 +
		output[off+1] = (byte)port;
532 +
	}
533 +
534 +
	/**
535 +
	 * Converts a port number into an array of bytes.
536 +
	 * 
537 +
	 * @param port  the port number
538 +
	 * @return an array of bytes
539 +
	 */
540 +
	public static byte[] portToBytes(int port) {
541 +
		byte[] buf = new byte[2];
542 +
		
543 +
		portToBytes(port, buf, 0);
544 +
		return buf;
545 +
	}
546 +
	
547 +
	/**
548 +
	 * Converts an array of bytes into a {@code short} value.
549 +
	 * 
550 +
	 * @param data the array of bytes
551 +
	 * @param off  starting position in the array of bytes
552 +
	 * @return the {@code short} value
553 +
	 */
554 +
	public static short toShort(byte[] data, int off) {
555 +
		return (short) (((int)data[off] << 8) | 
556 +
				((int)data[off+1] & 0xff)); 
557 +
	}
558 +
559 +
	/**
560 +
	 * Converts an array of bytes into a {@code short} value.
561 +
	 * 
562 +
	 * @param data the array of bytes
563 +
	 * @return the {@code short} value
564 +
	 */
565 +
	public static short toShort(byte[] data) {
566 +
		return toShort(data, 0); 
567 +
	}
568 +
	
569 +
	/**
570 +
	 * Converts a {@code short} value into an array of bytes.
571 +
	 * 
572 +
	 * @param value  the {@code short} value
573 +
	 * @param output an array for the output bytes
574 +
	 * @param off    starting position for the output bytes in the array
575 +
	 */
576 +
	public static void toBytes(short value, byte[] output, int off) {
577 +
		output[off  ] = (byte)(value >> 8);
578 +
		output[off+1] = (byte)value;
579 +
	}
580 +
581 +
	/**
582 +
	 * Converts a {@code short} value into an array of bytes.
583 +
	 * 
584 +
	 * @param value the short value
585 +
	 * @return an array of bytes
586 +
	 */
587 +
	public static byte[] toBytes(short value) {
588 +
		byte[] buf = new byte[2];
589 +
		
590 +
		toBytes(value, buf, 0);
591 +
		return buf;
592 +
	}
593 +
	
594 +
	/**
595 +
	 * Converts an array of bytes into an {@code int} value.
596 +
	 * 
597 +
	 * @param data the array of bytes
598 +
	 * @param off  starting position in the array of bytes
599 +
	 * @return the {@code int} value
600 +
	 */
601 +
	public static int toInt(byte[] data, int off) {
602 +
		return ((int)data[off] << 24) |
603 +
				((int)data[off+1] << 16) & 0xff0000 | 
604 +
				((int)data[off+2] <<  8) & 0xff00 | 
605 +
				((int)data[off+3]        & 0xff); 
606 +
	}
607 +
608 +
	/**
609 +
	 * Converts an array of bytes into an {@code int} value.
610 +
	 * 
611 +
	 * @param data the array of bytes
612 +
	 * @return the {@code int} value
613 +
	 */
614 +
	public static int toInt(byte[] data) {
615 +
		return toInt(data, 0); 
616 +
	}
617 +
	
618 +
	/**
619 +
	 * Converts an {@code int} value into an array of bytes.
620 +
	 * 
621 +
	 * @param value  the short value
622 +
	 * @param output an array for the output bytes
623 +
	 * @param off    starting position for the output bytes in the array
624 +
	 */
625 +
	public static void toBytes(int value, byte[] output, int off) {
626 +
		output[off  ] = (byte)(value >> 24);
627 +
		output[off+1] = (byte)(value >> 16);
628 +
		output[off+2] = (byte)(value >> 8);
629 +
		output[off+3] = (byte)value;
630 +
	}
631 +
632 +
	/**
633 +
	 * Converts an {@code int} value into an array of bytes.
634 +
	 * 
635 +
	 * @param value the short value
636 +
	 * @return an array of bytes
637 +
	 */
638 +
	public static byte[] toBytes(int value) {
639 +
		byte[] buf = new byte[4];
640 +
		
641 +
		toBytes(value, buf, 0);
642 +
		return buf;
643 +
	}
644 +
645 +
	/**
646 +
	 * Converts an array of bytes into a {@code long} value.
647 +
	 * 
648 +
	 * @param data the array of bytes
649 +
	 * @param off  starting position in the array of bytes
650 +
	 * @return the {@code long} value
651 +
	 */
652 +
	public static long toLong(byte[] data, int off) {
653 +
		return ((long)data[off] << 56) |
654 +
				((long)data[off+1] << 48) & 0xff000000000000L |
655 +
				((long)data[off+2] << 40) & 0xff0000000000L |
656 +
				((long)data[off+3] << 32) & 0xff00000000L |
657 +
				((long)data[off+4] << 24) & 0xff000000L |
658 +
				((long)data[off+5] << 16) & 0xff0000 | 
659 +
				((long)data[off+6] <<  8) & 0xff00 | 
660 +
				((long)data[off+7]        & 0xff); 
661 +
	}
662 +
663 +
	/**
664 +
	 * Converts an array of bytes into a {@code long} value.
665 +
	 * 
666 +
	 * @param data the array of bytes
667 +
	 * @return the {@code long} value
668 +
	 */
669 +
	public static long toLong(byte[] data) {
670 +
		return toLong(data, 0); 
671 +
	}
672 +
	
673 +
	/**
674 +
	 * Converts a {@code long} value into an array of bytes.
675 +
	 * 
676 +
	 * @param value  the short value
677 +
	 * @param output an array for the output bytes
678 +
	 * @param off    starting position for the output bytes in the array
679 +
	 */
680 +
	public static void toBytes(long value, byte[] output, int off) {
681 +
		output[off  ] = (byte)(value >> 56);
682 +
		output[off+1] = (byte)(value >> 48);
683 +
		output[off+2] = (byte)(value >> 40);
684 +
		output[off+3] = (byte)(value >> 32);
685 +
		output[off+4] = (byte)(value >> 24);
686 +
		output[off+5] = (byte)(value >> 16);
687 +
		output[off+6] = (byte)(value >> 8);
688 +
		output[off+7] = (byte)value;
689 +
	}
690 +
691 +
	/**
692 +
	 * Converts a {@code long} value into an array of bytes.
693 +
	 * 
694 +
	 * @param value the short value
695 +
	 * @return an array of bytes
696 +
	 */
697 +
	public static byte[] toBytes(long value) {
698 +
		byte[] buf = new byte[8];
699 +
		
700 +
		toBytes(value, buf, 0);
701 +
		return buf;
702 +
	}
703 +
	
704 +
}

@@ -0,0 +1,91 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
import java.nio.ByteBuffer;
29 +
30 +
class Socks5InitState extends AbstractSocksState implements ISocks5 {
31 +
	
32 +
	final static byte METHOD_INDEX = 1;
33 +
34 +
	private final static int RESPONSE_SIZE = 2;
35 +
36 +
	private final Socks5AuthMethod[] authMethods;
37 +
	
38 +
	private final AbstractSocksState[] nextStates;
39 +
	
40 +
	Socks5InitState(Socks5ProxyHandler handler, Socks5AuthMethod[] authMethods, AbstractSocksState[] nextStates) {
41 +
		super(handler);
42 +
		this.authMethods = authMethods;
43 +
		this.nextStates = nextStates;
44 +
	}
45 +
46 +
	@Override
47 +
	int responseSize() {
48 +
		return RESPONSE_SIZE;
49 +
	}
50 +
	
51 +
	@Override
52 +
	AbstractSocksState read(byte[] data) {
53 +
		if (data[VER_INDEX] != VERSION) {
54 +
			throw new ProxyConnectionException("Unsupported SOCKS5 reply version: " + data[0]);
55 +
		}
56 +
		
57 +
		byte methodCode = data[METHOD_INDEX];
58 +
		
59 +
		if (methodCode == Socks5AuthMethod.UNACCEPTED.code()) {
60 +
			throw new ProxyConnectionException("No acceptable authentication method");
61 +
		}
62 +
		
63 +
		Socks5AuthMethod method = null;
64 +
		AbstractSocksState next = null;
65 +
		
66 +
		for (int i=0; i<authMethods.length; ++i) {
67 +
			if (authMethods[i].code() == methodCode) {
68 +
				method = authMethods[i];
69 +
				next = nextStates[i];
70 +
				break;
71 +
			}
72 +
		}
73 +
		if (method == null) {
74 +
			throw new ProxyConnectionException("Unexpected authentication method: " + methodCode);
75 +
		}
76 +
		return next;
77 +
	}
78 +
79 +
	@Override
80 +
	void handleReady() {
81 +
		ByteBuffer buf = handler.getSession().allocate(2 + authMethods.length);
82 +
		
83 +
		buf.put(VERSION);
84 +
		buf.put((byte)authMethods.length);
85 +
		for (int i=0; i<authMethods.length; ++i) {
86 +
			buf.put(authMethods[i].code());
87 +
		}
88 +
		handler.flipAndWrite(buf);
89 +
	}
90 +
91 +
}

@@ -0,0 +1,64 @@
Loading
1 +
/*
2 +
 * -------------------------------- MIT License --------------------------------
3 +
 * 
4 +
 * Copyright (c) 2021 SNF4J contributors
5 +
 * 
6 +
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 +
 * of this software and associated documentation files (the "Software"), to deal
8 +
 * in the Software without restriction, including without limitation the rights
9 +
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 +
 * copies of the Software, and to permit persons to whom the Software is
11 +
 * furnished to do so, subject to the following conditions:
12 +
 * 
13 +
 * The above copyright notice and this permission notice shall be included in all
14 +
 * copies or substantial portions of the Software.
15 +
 * 
16 +
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 +
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 +
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 +
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 +
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 +
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 +
 * SOFTWARE.
23 +
 *
24 +
 * -----------------------------------------------------------------------------
25 +
 */
26 +
package org.snf4j.core.proxy;
27 +
28 +
/**
29 +
 * An {@code enum} that defines types of addresses in the replies from the
30 +
 * SOCKS server.
31 +
 * 
32 +
 * @author <a href="http://snf4j.org">SNF4J.ORG</a>
33 +
 */
34 +
public enum SocksAddressType {
35 +
36 +
	/** A version-4 IP address */
37 +
	IPV4((byte)1),
38 +
	
39 +
	/** A fully-qualified domain name */
40 +
	DOMAIN((byte)3),
41 +
42 +
	/** A version-6 IP address */
43 +
	IPV6((byte)4);
44 +
45 +
	private final byte code;
46 +
	
47 +
	SocksAddressType(byte code) {
48 +
		this.code = code;
49 +
	}
50 +
	
51 +
	byte code() {
52 +
		return code;
53 +
	}
54 +
55 +
	static SocksAddressType valueOf(byte code) {
56 +
		for (SocksAddressType value: values()) {
57 +
			if (value.code == code) {
58 +
				return value;
59 +
			}
60 +
		}
61 +
		return null;
62 +
	}
63 +
	
64 +
}
Files Coverage
snf4j-core-log4j2/src/main/java/org/snf4j/core/logger/impl 96.66%
snf4j-core-slf4j/src/main/java/org/snf4j/core/logger/impl 96.66%
snf4j-core/src/main/java/org/snf4j/core 97.90%
snf4j-sctp/src/main/java/org/snf4j/core 98.56%
snf4j-websocket/src/main/java/org/snf4j/websocket 99.30%
Project Totals (219 files) 98.20%
codecov-umbrella
Build #1463043007 -
1
coverage:
2
  range: "70...100"
3
  round: down
4
  precision: 2
5
  
6
  status:
7
    project:
8
      default:
9
        enabled: yes
10
        target: 94%
11
        threshold: 5%
12
        
13
    patch:
14
      default:
15
        enabled: yes
16
        target: 85%
17
        threshold: 5%
18
        
19
    changes: no
20
    
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.