backport socks codec to 3 branch
This commit is contained in:
parent
ca7702f38c
commit
9fcd31a4f4
4
pom.xml
4
pom.xml
|
@ -329,7 +329,7 @@
|
|||
<configuration>
|
||||
<signature>
|
||||
<groupId>org.codehaus.mojo.signature</groupId>
|
||||
<artifactId>java15</artifactId>
|
||||
<artifactId>java16</artifactId>
|
||||
<version>1.0</version>
|
||||
</signature>
|
||||
<ignores>
|
||||
|
@ -343,6 +343,8 @@
|
|||
<ignore>java.net.StandardProtocolFamily</ignore>
|
||||
<!-- Java Object Serialization -->
|
||||
<ignore>java.io.ObjectStreamClass</ignore>
|
||||
<!-- Socks Codec-->
|
||||
<ignore>java.net.IDN</ignore>
|
||||
</ignores>
|
||||
</configuration>
|
||||
<executions>
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
|
||||
/**
|
||||
* An socks auth request.
|
||||
*
|
||||
* @see {@link SocksAuthResponse}
|
||||
* @see {@link SocksAuthRequestDecoder}
|
||||
*/
|
||||
public final class SocksAuthRequest extends SocksRequest {
|
||||
private static final CharsetEncoder asciiEncoder = CharsetUtil.getEncoder(CharsetUtil.US_ASCII);
|
||||
private static final SubnegotiationVersion SUBNEGOTIATION_VERSION = SubnegotiationVersion.AUTH_PASSWORD;
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
public SocksAuthRequest(String username, String password) {
|
||||
super(SocksRequestType.AUTH);
|
||||
if (username == null) {
|
||||
throw new NullPointerException("username");
|
||||
}
|
||||
if (password == null) {
|
||||
throw new NullPointerException("username");
|
||||
}
|
||||
if (!asciiEncoder.canEncode(username) || !asciiEncoder.canEncode(password)) {
|
||||
throw new IllegalArgumentException(" username: " + username + " or password: " + password +
|
||||
" values should be in pure ascii");
|
||||
}
|
||||
if (username.length() > 255) {
|
||||
throw new IllegalArgumentException(username + " exceeds 255 char limit");
|
||||
}
|
||||
if (password.length() > 255) {
|
||||
throw new IllegalArgumentException(password + " exceeds 255 char limit");
|
||||
}
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns username that needs to be authenticated
|
||||
*
|
||||
* @return username that needs to be authenticated
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns password that needs to be validated
|
||||
*
|
||||
* @return password that needs to be validated
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer channelBuffer) throws Exception {
|
||||
channelBuffer.writeByte(SUBNEGOTIATION_VERSION.getByteValue());
|
||||
channelBuffer.writeByte(username.length());
|
||||
channelBuffer.writeBytes(username.getBytes("US-ASCII"));
|
||||
channelBuffer.writeByte(password.length());
|
||||
channelBuffer.writeBytes(password.getBytes("US-ASCII"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* Decodes {@link ChannelBuffer}s into {@link SocksAuthRequest}.
|
||||
* Before returning SocksRequest decoder removes itself from pipeline.
|
||||
*/
|
||||
public class SocksAuthRequestDecoder extends ReplayingDecoder<SocksAuthRequestDecoder.State> {
|
||||
private static final String name = "SOCKS_AUTH_REQUEST_DECODER";
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private SocksMessage.SubnegotiationVersion version;
|
||||
private int fieldLength;
|
||||
private String username;
|
||||
private String password;
|
||||
private SocksRequest msg = SocksCommonUtils.UNKNOWN_SOCKS_REQUEST;
|
||||
|
||||
public SocksAuthRequestDecoder() {
|
||||
super(State.CHECK_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelBuffer buffer, State state) throws Exception {
|
||||
switch (state) {
|
||||
case CHECK_PROTOCOL_VERSION: {
|
||||
version = SocksMessage.SubnegotiationVersion.fromByte(buffer.readByte());
|
||||
if (version != SocksMessage.SubnegotiationVersion.AUTH_PASSWORD) {
|
||||
break;
|
||||
}
|
||||
checkpoint(State.READ_USERNAME);
|
||||
}
|
||||
case READ_USERNAME: {
|
||||
fieldLength = buffer.readByte();
|
||||
username = buffer.readBytes(fieldLength).toString(CharsetUtil.US_ASCII);
|
||||
checkpoint(State.READ_PASSWORD);
|
||||
}
|
||||
case READ_PASSWORD: {
|
||||
fieldLength = buffer.readByte();
|
||||
password = buffer.readBytes(fieldLength).toString(CharsetUtil.US_ASCII);
|
||||
msg = new SocksAuthRequest(username, password);
|
||||
}
|
||||
}
|
||||
ctx.getPipeline().remove(this);
|
||||
return msg;
|
||||
}
|
||||
|
||||
enum State {
|
||||
CHECK_PROTOCOL_VERSION,
|
||||
READ_USERNAME,
|
||||
READ_PASSWORD
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* An socks auth response.
|
||||
*
|
||||
* @see SocksAuthRequest
|
||||
* @see SocksAuthResponseDecoder
|
||||
*/
|
||||
public final class SocksAuthResponse extends SocksResponse {
|
||||
private static final SubnegotiationVersion SUBNEGOTIATION_VERSION = SubnegotiationVersion.AUTH_PASSWORD;
|
||||
private final AuthStatus authStatus;
|
||||
|
||||
public SocksAuthResponse(AuthStatus authStatus) {
|
||||
super(SocksResponseType.AUTH);
|
||||
if (authStatus == null) {
|
||||
throw new NullPointerException("authStatus");
|
||||
}
|
||||
this.authStatus = authStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthStatus} of this {@link SocksAuthResponse}
|
||||
*/
|
||||
public AuthStatus getAuthStatus() {
|
||||
return authStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer channelBuffer) {
|
||||
channelBuffer.writeByte(SUBNEGOTIATION_VERSION.getByteValue());
|
||||
channelBuffer.writeByte(authStatus.getByteValue());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
|
||||
|
||||
/**
|
||||
* Decodes {@link ChannelBuffer}s into {@link SocksAuthResponse}.
|
||||
* Before returning SocksResponse decoder removes itself from pipeline.
|
||||
*/
|
||||
public class SocksAuthResponseDecoder extends ReplayingDecoder<SocksAuthResponseDecoder.State> {
|
||||
private static final String name = "SOCKS_AUTH_RESPONSE_DECODER";
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private SocksMessage.SubnegotiationVersion version;
|
||||
private SocksMessage.AuthStatus authStatus;
|
||||
private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE;
|
||||
|
||||
public SocksAuthResponseDecoder() {
|
||||
super(State.CHECK_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelBuffer buffer, State state) throws Exception {
|
||||
switch (state) {
|
||||
case CHECK_PROTOCOL_VERSION: {
|
||||
version = SocksMessage.SubnegotiationVersion.fromByte(buffer.readByte());
|
||||
if (version != SocksMessage.SubnegotiationVersion.AUTH_PASSWORD) {
|
||||
break;
|
||||
}
|
||||
checkpoint(State.READ_AUTH_RESPONSE);
|
||||
}
|
||||
case READ_AUTH_RESPONSE: {
|
||||
authStatus = SocksMessage.AuthStatus.fromByte(buffer.readByte());
|
||||
msg = new SocksAuthResponse(authStatus);
|
||||
}
|
||||
}
|
||||
ctx.getPipeline().remove(this);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public enum State {
|
||||
CHECK_PROTOCOL_VERSION,
|
||||
READ_AUTH_RESPONSE
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.util.NetUtil;
|
||||
import org.jboss.netty.util.internal.DetectionUtil;
|
||||
|
||||
import java.net.IDN;
|
||||
|
||||
/**
|
||||
* An socks cmd request.
|
||||
*
|
||||
* @see {@link SocksCmdResponse}
|
||||
* @see {@link SocksCmdRequestDecoder}
|
||||
*/
|
||||
public final class SocksCmdRequest extends SocksRequest {
|
||||
private final CmdType cmdType;
|
||||
private final AddressType addressType;
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
public SocksCmdRequest(CmdType cmdType, AddressType addressType, String host, int port) {
|
||||
super(SocksRequestType.CMD);
|
||||
if (DetectionUtil.javaVersion() < 6) {
|
||||
throw new IllegalStateException("Only supported with Java version 6+");
|
||||
}
|
||||
if (cmdType == null) {
|
||||
throw new NullPointerException("cmdType");
|
||||
}
|
||||
if (addressType == null) {
|
||||
throw new NullPointerException("addressType");
|
||||
}
|
||||
if (host == null) {
|
||||
throw new NullPointerException("host");
|
||||
}
|
||||
switch (addressType) {
|
||||
case IPv4:
|
||||
if (!NetUtil.isValidIpV4Address(host)) {
|
||||
throw new IllegalArgumentException(host + " is not a valid IPv4 address");
|
||||
}
|
||||
break;
|
||||
case DOMAIN:
|
||||
if (IDN.toASCII(host).length() > 255) {
|
||||
throw new IllegalArgumentException(host + " IDN: " + IDN.toASCII(host) + " exceeds 255 char limit");
|
||||
}
|
||||
break;
|
||||
case IPv6:
|
||||
if (!NetUtil.isValidIpV6Address(host)) {
|
||||
throw new IllegalArgumentException(host + " is not a valid IPv6 address");
|
||||
}
|
||||
break;
|
||||
case UNKNOWN:
|
||||
break;
|
||||
}
|
||||
if (port < 0 && port >= 65535) {
|
||||
throw new IllegalArgumentException(port + " is not in bounds 0 < x < 65536");
|
||||
}
|
||||
this.cmdType = cmdType;
|
||||
this.addressType = addressType;
|
||||
this.host = IDN.toASCII(host);
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link SocksMessage.CmdType} of this {@link SocksCmdRequest}
|
||||
*/
|
||||
public CmdType getCmdType() {
|
||||
return cmdType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link AddressType} of this {@link SocksCmdRequest}
|
||||
*/
|
||||
public AddressType getAddressType() {
|
||||
return addressType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns host that is used as a parameter in {@link SocksMessage.CmdType}
|
||||
*/
|
||||
public String getHost() {
|
||||
return IDN.toUnicode(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns port that is used as a parameter in {@link SocksMessage.CmdType}
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer channelBuffer) throws Exception {
|
||||
channelBuffer.writeByte(getProtocolVersion().getByteValue());
|
||||
channelBuffer.writeByte(cmdType.getByteValue());
|
||||
channelBuffer.writeByte(0x00);
|
||||
channelBuffer.writeByte(addressType.getByteValue());
|
||||
switch (addressType) {
|
||||
case IPv4: {
|
||||
channelBuffer.writeBytes(NetUtil.createByteArrayFromIpAddressString(host));
|
||||
channelBuffer.writeShort(port);
|
||||
break;
|
||||
}
|
||||
|
||||
case DOMAIN: {
|
||||
channelBuffer.writeByte(host.length());
|
||||
channelBuffer.writeBytes(host.getBytes("US-ASCII"));
|
||||
channelBuffer.writeShort(port);
|
||||
break;
|
||||
}
|
||||
|
||||
case IPv6: {
|
||||
channelBuffer.writeBytes(NetUtil.createByteArrayFromIpAddressString(host));
|
||||
channelBuffer.writeShort(port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* Decodes {@link ChannelBuffer}s into {@link SocksCmdRequest}.
|
||||
* Before returning SocksRequest decoder removes itself from pipeline.
|
||||
*/
|
||||
public class SocksCmdRequestDecoder extends ReplayingDecoder<SocksCmdRequestDecoder.State> {
|
||||
private static final String name = "SOCKS_CMD_REQUEST_DECODER";
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private SocksMessage.ProtocolVersion version;
|
||||
private int fieldLength;
|
||||
private SocksMessage.CmdType cmdType;
|
||||
private SocksMessage.AddressType addressType;
|
||||
private byte reserved;
|
||||
private String host;
|
||||
private int port;
|
||||
private SocksRequest msg = SocksCommonUtils.UNKNOWN_SOCKS_REQUEST;
|
||||
|
||||
public SocksCmdRequestDecoder() {
|
||||
super(State.CHECK_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelBuffer buffer, State state) throws Exception {
|
||||
switch (state) {
|
||||
case CHECK_PROTOCOL_VERSION: {
|
||||
version = SocksMessage.ProtocolVersion.fromByte(buffer.readByte());
|
||||
if (version != SocksMessage.ProtocolVersion.SOCKS5) {
|
||||
break;
|
||||
}
|
||||
checkpoint(State.READ_CMD_HEADER);
|
||||
}
|
||||
case READ_CMD_HEADER: {
|
||||
cmdType = SocksMessage.CmdType.fromByte(buffer.readByte());
|
||||
reserved = buffer.readByte();
|
||||
addressType = SocksMessage.AddressType.fromByte(buffer.readByte());
|
||||
checkpoint(State.READ_CMD_ADDRESS);
|
||||
}
|
||||
case READ_CMD_ADDRESS: {
|
||||
switch (addressType) {
|
||||
case IPv4: {
|
||||
host = SocksCommonUtils.intToIp(buffer.readInt());
|
||||
port = buffer.readUnsignedShort();
|
||||
msg = new SocksCmdRequest(cmdType, addressType, host, port);
|
||||
break;
|
||||
}
|
||||
case DOMAIN: {
|
||||
fieldLength = buffer.readByte();
|
||||
host = buffer.readBytes(fieldLength).toString(CharsetUtil.US_ASCII);
|
||||
port = buffer.readUnsignedShort();
|
||||
msg = new SocksCmdRequest(cmdType, addressType, host, port);
|
||||
break;
|
||||
}
|
||||
case IPv6: {
|
||||
host = SocksCommonUtils.ipv6toStr(buffer.readBytes(16).array());
|
||||
port = buffer.readUnsignedShort();
|
||||
msg = new SocksCmdRequest(cmdType, addressType, host, port);
|
||||
break;
|
||||
}
|
||||
case UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.getPipeline().remove(this);
|
||||
return msg;
|
||||
}
|
||||
|
||||
enum State {
|
||||
CHECK_PROTOCOL_VERSION,
|
||||
READ_CMD_HEADER,
|
||||
READ_CMD_ADDRESS
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* An socks cmd response.
|
||||
*
|
||||
* @see SocksCmdRequest
|
||||
* @see SocksCmdResponseDecoder
|
||||
*/
|
||||
public final class SocksCmdResponse extends SocksResponse {
|
||||
private final CmdStatus cmdStatus;
|
||||
|
||||
private final AddressType addressType;
|
||||
// All arrays are initialized on construction time to 0/false/null remove array Initialization
|
||||
private static final byte[] IPv4_HOSTNAME_ZEROED = {0x00, 0x00, 0x00, 0x00};
|
||||
private static final byte[] IPv6_HOSTNAME_ZEROED = {0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
public SocksCmdResponse(CmdStatus cmdStatus, AddressType addressType) {
|
||||
super(SocksResponseType.CMD);
|
||||
if (cmdStatus == null) {
|
||||
throw new NullPointerException("cmdStatus");
|
||||
}
|
||||
if (addressType == null) {
|
||||
throw new NullPointerException("addressType");
|
||||
}
|
||||
this.cmdStatus = cmdStatus;
|
||||
this.addressType = addressType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link CmdStatus} of this {@link SocksCmdResponse}
|
||||
*
|
||||
* @return The {@link CmdStatus} of this {@link SocksCmdResponse}
|
||||
*/
|
||||
public CmdStatus getCmdStatus() {
|
||||
return cmdStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link AddressType} of this {@link SocksCmdResponse}
|
||||
*
|
||||
* @return The {@link AddressType} of this {@link SocksCmdResponse}
|
||||
*/
|
||||
public AddressType getAddressType() {
|
||||
return addressType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer channelBuffer) {
|
||||
channelBuffer.writeByte(getProtocolVersion().getByteValue());
|
||||
channelBuffer.writeByte(cmdStatus.getByteValue());
|
||||
channelBuffer.writeByte(0x00);
|
||||
channelBuffer.writeByte(addressType.getByteValue());
|
||||
switch (addressType) {
|
||||
case IPv4: {
|
||||
channelBuffer.writeBytes(IPv4_HOSTNAME_ZEROED);
|
||||
channelBuffer.writeShort(0);
|
||||
break;
|
||||
}
|
||||
case DOMAIN: {
|
||||
channelBuffer.writeByte(1); // domain length
|
||||
channelBuffer.writeByte(0); // domain value
|
||||
channelBuffer.writeShort(0); // port value
|
||||
break;
|
||||
}
|
||||
case IPv6: {
|
||||
channelBuffer.writeBytes(IPv6_HOSTNAME_ZEROED);
|
||||
channelBuffer.writeShort(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* Decodes {@link ChannelBuffer}s into {@link SocksCmdResponse}.
|
||||
* Before returning SocksResponse decoder removes itself from pipeline.
|
||||
*/
|
||||
public class SocksCmdResponseDecoder extends ReplayingDecoder<SocksCmdResponseDecoder.State> {
|
||||
private static final String name = "SOCKS_CMD_RESPONSE_DECODER";
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private SocksMessage.ProtocolVersion version;
|
||||
private int fieldLength;
|
||||
private SocksMessage.CmdStatus cmdStatus;
|
||||
private SocksMessage.AddressType addressType;
|
||||
private byte reserved;
|
||||
private String host;
|
||||
private int port;
|
||||
private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE;
|
||||
|
||||
public SocksCmdResponseDecoder() {
|
||||
super(State.CHECK_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelBuffer buffer, State state) throws Exception {
|
||||
switch (state) {
|
||||
case CHECK_PROTOCOL_VERSION: {
|
||||
version = SocksMessage.ProtocolVersion.fromByte(buffer.readByte());
|
||||
if (version != SocksMessage.ProtocolVersion.SOCKS5) {
|
||||
break;
|
||||
}
|
||||
checkpoint(State.READ_CMD_HEADER);
|
||||
}
|
||||
case READ_CMD_HEADER: {
|
||||
cmdStatus = SocksMessage.CmdStatus.fromByte(buffer.readByte());
|
||||
reserved = buffer.readByte();
|
||||
addressType = SocksMessage.AddressType.fromByte(buffer.readByte());
|
||||
checkpoint(State.READ_CMD_ADDRESS);
|
||||
}
|
||||
case READ_CMD_ADDRESS: {
|
||||
switch (addressType) {
|
||||
case IPv4: {
|
||||
host = SocksCommonUtils.intToIp(buffer.readInt());
|
||||
port = buffer.readUnsignedShort();
|
||||
msg = new SocksCmdResponse(cmdStatus, addressType);
|
||||
break;
|
||||
}
|
||||
case DOMAIN: {
|
||||
fieldLength = buffer.readByte();
|
||||
host = buffer.readBytes(fieldLength).toString(CharsetUtil.US_ASCII);
|
||||
port = buffer.readUnsignedShort();
|
||||
msg = new SocksCmdResponse(cmdStatus, addressType);
|
||||
break;
|
||||
}
|
||||
case IPv6: {
|
||||
host = SocksCommonUtils.ipv6toStr(buffer.readBytes(16).array());
|
||||
port = buffer.readUnsignedShort();
|
||||
msg = new SocksCmdResponse(cmdStatus, addressType);
|
||||
break;
|
||||
}
|
||||
case UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.getPipeline().remove(this);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public enum State {
|
||||
CHECK_PROTOCOL_VERSION,
|
||||
READ_CMD_HEADER,
|
||||
READ_CMD_ADDRESS
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
final class SocksCommonUtils {
|
||||
public static final SocksRequest UNKNOWN_SOCKS_REQUEST = new UnknownSocksRequest();
|
||||
public static final SocksResponse UNKNOWN_SOCKS_RESPONSE = new UnknownSocksResponse();
|
||||
|
||||
private static final int SECOND_ADDRESS_OCTET_SHIFT = 16;
|
||||
private static final int FIRST_ADDRESS_OCTET_SHIFT = 24;
|
||||
private static final int THIRD_ADDRESS_OCTET_SHIFT = 8;
|
||||
private static final int XOR_DEFAULT_VALUE = 0xff;
|
||||
|
||||
/**
|
||||
* A constructor to stop this class being constructed.
|
||||
*/
|
||||
private SocksCommonUtils() {
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public static String intToIp(int i) {
|
||||
return String.valueOf(i >> FIRST_ADDRESS_OCTET_SHIFT & XOR_DEFAULT_VALUE) + '.' +
|
||||
(i >> SECOND_ADDRESS_OCTET_SHIFT & XOR_DEFAULT_VALUE) + '.' +
|
||||
(i >> THIRD_ADDRESS_OCTET_SHIFT & XOR_DEFAULT_VALUE) + '.' +
|
||||
(i & XOR_DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
private static final char[] ipv6conseqZeroFiller = {':', ':'};
|
||||
private static final char ipv6hextetSeparator = ':';
|
||||
|
||||
/*
|
||||
* Convert numeric IPv6 to compressed format, where
|
||||
* the longest sequence of 0's (with 2 or more 0's) is replaced with "::"
|
||||
*/
|
||||
public static String ipv6toCompressedForm(byte[] src) {
|
||||
assert src.length == 16;
|
||||
//Find the longest sequence of 0's
|
||||
//start of compressed region (hextet index)
|
||||
int cmprHextet = -1;
|
||||
//length of compressed region
|
||||
int cmprSize = 0;
|
||||
for (int hextet = 0; hextet < 8;) {
|
||||
int curByte = hextet * 2;
|
||||
int size = 0;
|
||||
while (curByte < src.length && src[curByte] == 0
|
||||
&& src[curByte + 1] == 0) {
|
||||
curByte += 2;
|
||||
size++;
|
||||
}
|
||||
if (size > cmprSize) {
|
||||
cmprHextet = hextet;
|
||||
cmprSize = size;
|
||||
}
|
||||
hextet = curByte / 2 + 1;
|
||||
}
|
||||
if (cmprHextet == -1 || cmprSize < 2) {
|
||||
//No compression can be applied
|
||||
return ipv6toStr(src);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(39);
|
||||
ipv6toStr(sb, src, 0, cmprHextet);
|
||||
sb.append(ipv6conseqZeroFiller);
|
||||
ipv6toStr(sb, src, cmprHextet + cmprSize, 8);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert numeric IPv6 to standard (non-compressed) format.
|
||||
*
|
||||
* Borrowed from Inet6Address.java #numericToTextFormat(byte[])
|
||||
* Changed StringBuffer -> StringBuilder and ":" -> ':' for performance.
|
||||
*/
|
||||
public static String ipv6toStr(byte[] src) {
|
||||
assert src.length == 16;
|
||||
StringBuilder sb = new StringBuilder(39);
|
||||
ipv6toStr(sb, src, 0, 8);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void ipv6toStr(StringBuilder sb, byte[] src,
|
||||
int fromHextet, int toHextet) {
|
||||
for (int i = fromHextet; i < toHextet; i++) {
|
||||
sb.append(Integer.toHexString(src[i << 1] << 8 & 0xff00
|
||||
| src[(i << 1) + 1] & 0xff));
|
||||
if (i < toHextet - 1) {
|
||||
sb.append(ipv6hextetSeparator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An socks init request.
|
||||
*
|
||||
* @see {@link SocksInitResponse}
|
||||
* @see {@link SocksInitRequestDecoder}
|
||||
*/
|
||||
public final class SocksInitRequest extends SocksRequest {
|
||||
private final List<AuthScheme> authSchemes;
|
||||
|
||||
public SocksInitRequest(List<AuthScheme> authSchemes) {
|
||||
super(SocksRequestType.INIT);
|
||||
if (authSchemes == null) {
|
||||
throw new NullPointerException("authSchemes");
|
||||
}
|
||||
this.authSchemes = authSchemes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the List<{@link AuthScheme}> of this {@link SocksInitRequest}
|
||||
|
||||
*/
|
||||
public List<AuthScheme> getAuthSchemes() {
|
||||
return Collections.unmodifiableList(authSchemes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer channelBuffer) {
|
||||
channelBuffer.writeByte(getProtocolVersion().getByteValue());
|
||||
channelBuffer.writeByte(authSchemes.size());
|
||||
for (AuthScheme authScheme : authSchemes) {
|
||||
channelBuffer.writeByte(authScheme.getByteValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Decodes {@link ChannelBuffer}s into {@link SocksInitRequest}.
|
||||
* Before returning SocksRequest decoder removes itself from pipeline.
|
||||
*/
|
||||
public class SocksInitRequestDecoder extends ReplayingDecoder<SocksInitRequestDecoder.State> {
|
||||
private static final String name = "SOCKS_INIT_REQUEST_DECODER";
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private final List<SocksMessage.AuthScheme> authSchemes = new ArrayList<SocksMessage.AuthScheme>();
|
||||
private SocksMessage.ProtocolVersion version;
|
||||
private byte authSchemeNum;
|
||||
private SocksRequest msg = SocksCommonUtils.UNKNOWN_SOCKS_REQUEST;
|
||||
|
||||
public SocksInitRequestDecoder() {
|
||||
super(State.CHECK_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelBuffer buffer, State state) throws Exception {
|
||||
switch (state) {
|
||||
case CHECK_PROTOCOL_VERSION: {
|
||||
version = SocksMessage.ProtocolVersion.fromByte(buffer.readByte());
|
||||
if (version != SocksMessage.ProtocolVersion.SOCKS5) {
|
||||
break;
|
||||
}
|
||||
checkpoint(State.READ_AUTH_SCHEMES);
|
||||
}
|
||||
case READ_AUTH_SCHEMES: {
|
||||
authSchemes.clear();
|
||||
authSchemeNum = buffer.readByte();
|
||||
for (int i = 0; i < authSchemeNum; i++) {
|
||||
authSchemes.add(SocksMessage.AuthScheme.fromByte(buffer.readByte()));
|
||||
}
|
||||
msg = new SocksInitRequest(authSchemes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx.getPipeline().remove(this);
|
||||
return msg;
|
||||
}
|
||||
|
||||
enum State {
|
||||
CHECK_PROTOCOL_VERSION,
|
||||
READ_AUTH_SCHEMES
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* An socks init response.
|
||||
*
|
||||
* @see {@link SocksInitRequest}
|
||||
* @see {@link SocksInitResponseDecoder}
|
||||
*/
|
||||
public final class SocksInitResponse extends SocksResponse {
|
||||
private final AuthScheme authScheme;
|
||||
|
||||
public SocksInitResponse(AuthScheme authScheme) {
|
||||
super(SocksResponseType.INIT);
|
||||
if (authScheme == null) {
|
||||
throw new NullPointerException("authScheme");
|
||||
}
|
||||
this.authScheme = authScheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthScheme} of this {@link SocksInitResponse}
|
||||
*/
|
||||
public AuthScheme getAuthScheme() {
|
||||
return authScheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer channelBuffer) {
|
||||
channelBuffer.writeByte(getProtocolVersion().getByteValue());
|
||||
channelBuffer.writeByte(authScheme.getByteValue());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
|
||||
|
||||
/**
|
||||
* Decodes {@link ChannelBuffer}s into {@link SocksInitResponse}.
|
||||
* Before returning SocksResponse decoder removes itself from pipeline.
|
||||
*/
|
||||
public class SocksInitResponseDecoder extends ReplayingDecoder<SocksInitResponseDecoder.State> {
|
||||
private static final String name = "SOCKS_INIT_RESPONSE_DECODER";
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private SocksMessage.ProtocolVersion version;
|
||||
private SocksMessage.AuthScheme authScheme;
|
||||
|
||||
private SocksResponse msg = SocksCommonUtils.UNKNOWN_SOCKS_RESPONSE;
|
||||
|
||||
public SocksInitResponseDecoder() {
|
||||
super(State.CHECK_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelBuffer buffer, State state) throws Exception {
|
||||
switch (state) {
|
||||
case CHECK_PROTOCOL_VERSION: {
|
||||
version = SocksMessage.ProtocolVersion.fromByte(buffer.readByte());
|
||||
if (version != SocksMessage.ProtocolVersion.SOCKS5) {
|
||||
break;
|
||||
}
|
||||
checkpoint(State.READ_PREFFERED_AUTH_TYPE);
|
||||
}
|
||||
case READ_PREFFERED_AUTH_TYPE: {
|
||||
authScheme = SocksMessage.AuthScheme.fromByte(buffer.readByte());
|
||||
msg = new SocksInitResponse(authScheme);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx.getPipeline().remove(this);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public enum State {
|
||||
CHECK_PROTOCOL_VERSION,
|
||||
READ_PREFFERED_AUTH_TYPE
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* An abstract class that defines a SocksMessage, providing common properties for
|
||||
* {@link SocksRequest} and {@link SocksResponse}.
|
||||
*
|
||||
* @see SocksRequest
|
||||
* @see SocksResponse
|
||||
*/
|
||||
|
||||
public abstract class SocksMessage {
|
||||
private final MessageType messageType;
|
||||
private final ProtocolVersion protocolVersion = ProtocolVersion.SOCKS5;
|
||||
|
||||
protected SocksMessage(MessageType messageType) {
|
||||
if (messageType == null) {
|
||||
throw new NullPointerException("messageType");
|
||||
}
|
||||
this.messageType = messageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MessageType} of this {@link SocksMessage}
|
||||
*
|
||||
* @return The {@link MessageType} of this {@link SocksMessage}
|
||||
*/
|
||||
public MessageType getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
public enum MessageType {
|
||||
REQUEST,
|
||||
RESPONSE,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
public enum AuthScheme {
|
||||
NO_AUTH((byte) 0x00),
|
||||
AUTH_GSSAPI((byte) 0x01),
|
||||
AUTH_PASSWORD((byte) 0x02),
|
||||
UNKNOWN((byte) 0xff);
|
||||
|
||||
private final byte b;
|
||||
|
||||
AuthScheme(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static AuthScheme fromByte(byte b) {
|
||||
for (AuthScheme code : values()) {
|
||||
if (code.b == b) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public byte getByteValue() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CmdType {
|
||||
CONNECT((byte) 0x01),
|
||||
BIND((byte) 0x02),
|
||||
UDP((byte) 0x03),
|
||||
UNKNOWN((byte) 0xff);
|
||||
|
||||
private final byte b;
|
||||
|
||||
CmdType(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static CmdType fromByte(byte b) {
|
||||
for (CmdType code : values()) {
|
||||
if (code.b == b) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public byte getByteValue() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public enum AddressType {
|
||||
IPv4((byte) 0x01),
|
||||
DOMAIN((byte) 0x03),
|
||||
IPv6((byte) 0x04),
|
||||
UNKNOWN((byte) 0xff);
|
||||
|
||||
private final byte b;
|
||||
|
||||
AddressType(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static AddressType fromByte(byte b) {
|
||||
for (AddressType code : values()) {
|
||||
if (code.b == b) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public byte getByteValue() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public enum AuthStatus {
|
||||
SUCCESS((byte) 0x00),
|
||||
FAILURE((byte) 0xff);
|
||||
|
||||
private final byte b;
|
||||
|
||||
AuthStatus(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static AuthStatus fromByte(byte b) {
|
||||
for (AuthStatus code : values()) {
|
||||
if (code.b == b) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
public byte getByteValue() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CmdStatus {
|
||||
SUCCESS((byte) 0x00),
|
||||
FAILURE((byte) 0x01),
|
||||
FORBIDDEN((byte) 0x02),
|
||||
NETWORK_UNREACHABLE((byte) 0x03),
|
||||
HOST_UNREACHABLE((byte) 0x04),
|
||||
REFUSED((byte) 0x05),
|
||||
TTL_EXPIRED((byte) 0x06),
|
||||
COMMAND_NOT_SUPPORTED((byte) 0x07),
|
||||
ADDRESS_NOT_SUPPORTED((byte) 0x08),
|
||||
UNASSIGNED((byte) 0xff);
|
||||
|
||||
private final byte b;
|
||||
|
||||
CmdStatus(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static CmdStatus fromByte(byte b) {
|
||||
for (CmdStatus code : values()) {
|
||||
if (code.b == b) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return UNASSIGNED;
|
||||
}
|
||||
|
||||
public byte getByteValue() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ProtocolVersion {
|
||||
SOCKS4a((byte) 0x04),
|
||||
SOCKS5((byte) 0x05),
|
||||
UNKNOWN((byte) 0xff);
|
||||
|
||||
private final byte b;
|
||||
|
||||
ProtocolVersion(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static ProtocolVersion fromByte(byte b) {
|
||||
for (ProtocolVersion code : values()) {
|
||||
if (code.b == b) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public byte getByteValue() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SubnegotiationVersion {
|
||||
AUTH_PASSWORD((byte) 0x01),
|
||||
UNKNOWN((byte) 0xff);
|
||||
|
||||
private final byte b;
|
||||
|
||||
SubnegotiationVersion(byte b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static SubnegotiationVersion fromByte(byte b) {
|
||||
for (SubnegotiationVersion code : values()) {
|
||||
if (code.b == b) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public byte getByteValue() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link ProtocolVersion} of this {@link SocksMessage}
|
||||
*
|
||||
* @return The {@link ProtocolVersion} of this {@link SocksMessage}
|
||||
*/
|
||||
public ProtocolVersion getProtocolVersion() {
|
||||
return protocolVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode socks message into its byte representation and write it into byteBuf
|
||||
*
|
||||
* @see ChannelBuffer
|
||||
*/
|
||||
public abstract void encodeAsByteBuf(ChannelBuffer channelBuffer) throws Exception;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandler;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
|
||||
/**
|
||||
* Encodes an {@link SocksMessage} into a {@link ChannelBuffer}.
|
||||
* {@link OneToOneEncoder} implementation.
|
||||
* Use this with {@link SocksInitRequest}, {@link SocksInitResponse}, {@link SocksAuthRequest},
|
||||
* {@link SocksAuthResponse}, {@link SocksCmdRequest} and {@link SocksCmdResponse}
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
public class SocksMessageEncoder extends OneToOneEncoder {
|
||||
private static final String name = "SOCKS_MESSAGE_ENCODER";
|
||||
private static final int DEFAULT_ENCODER_BUFFER_SIZE = 1024;
|
||||
|
||||
public static String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
|
||||
ChannelBuffer buffer = null;
|
||||
if (msg instanceof SocksMessage) {
|
||||
buffer = ChannelBuffers.buffer(DEFAULT_ENCODER_BUFFER_SIZE);
|
||||
((SocksMessage) msg).encodeAsByteBuf(buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
/**
|
||||
* An abstract class that defines a SocksRequest, providing common properties for
|
||||
* {@link SocksInitRequest}, {@link SocksAuthRequest}, {@link SocksCmdRequest} and {@link UnknownSocksRequest}.
|
||||
*
|
||||
* @see {@link SocksInitRequest}
|
||||
* @see {@link SocksAuthRequest}
|
||||
* @see {@link SocksCmdRequest}
|
||||
* @see {@link UnknownSocksRequest}
|
||||
*/
|
||||
public abstract class SocksRequest extends SocksMessage {
|
||||
private final SocksRequestType socksRequestType;
|
||||
|
||||
protected SocksRequest(SocksRequestType socksRequestType) {
|
||||
super(MessageType.REQUEST);
|
||||
if (socksRequestType == null) {
|
||||
throw new NullPointerException("socksRequestType");
|
||||
}
|
||||
this.socksRequestType = socksRequestType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns socks request type
|
||||
*
|
||||
* @return socks request type
|
||||
*/
|
||||
public SocksRequestType getSocksRequestType() {
|
||||
return socksRequestType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of socks request
|
||||
*/
|
||||
public enum SocksRequestType {
|
||||
INIT,
|
||||
AUTH,
|
||||
CMD,
|
||||
UNKNOWN
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
/**
|
||||
* An abstract class that defines a SocksResponse, providing common properties for
|
||||
* {@link SocksInitResponse}, {@link SocksAuthResponse}, {@link SocksCmdResponse} and {@link UnknownSocksResponse}.
|
||||
*
|
||||
* @see {@link SocksInitResponse}
|
||||
* @see {@link SocksAuthResponse}
|
||||
* @see {@link SocksCmdResponse}
|
||||
* @see {@link UnknownSocksResponse}
|
||||
*/
|
||||
public abstract class SocksResponse extends SocksMessage {
|
||||
private final SocksResponseType socksResponseType;
|
||||
|
||||
protected SocksResponse(SocksResponseType socksResponseType) {
|
||||
super(MessageType.RESPONSE);
|
||||
if (socksResponseType == null) {
|
||||
throw new NullPointerException("socksResponseType");
|
||||
}
|
||||
this.socksResponseType = socksResponseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns socks response type
|
||||
*
|
||||
* @return socks response type
|
||||
*/
|
||||
public SocksResponseType getSocksResponseType() {
|
||||
return socksResponseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of socks response
|
||||
*/
|
||||
public enum SocksResponseType {
|
||||
INIT,
|
||||
AUTH,
|
||||
CMD,
|
||||
UNKNOWN
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* An unknown socks message.
|
||||
*
|
||||
* @see {@link UnknownSocksRequest}
|
||||
* @see {@link UnknownSocksResponse}
|
||||
*/
|
||||
public final class UnknownSocksMessage extends SocksMessage {
|
||||
|
||||
public UnknownSocksMessage() {
|
||||
super(MessageType.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer byteBuf) {
|
||||
// NOOP
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* An unknown socks request.
|
||||
*
|
||||
* @see {@link SocksInitRequestDecoder}
|
||||
* @see {@link SocksAuthRequestDecoder}
|
||||
* @see {@link SocksCmdRequestDecoder}
|
||||
*/
|
||||
public final class UnknownSocksRequest extends SocksRequest {
|
||||
|
||||
public UnknownSocksRequest() {
|
||||
super(SocksRequestType.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer buffer) {
|
||||
// NOOP
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
/**
|
||||
* An unknown socks response.
|
||||
*
|
||||
* @see {@link SocksInitResponseDecoder}
|
||||
* @see {@link SocksAuthResponseDecoder}
|
||||
* @see {@link SocksCmdResponseDecoder}
|
||||
*/
|
||||
public final class UnknownSocksResponse extends SocksResponse {
|
||||
|
||||
public UnknownSocksResponse() {
|
||||
super(SocksResponseType.UNKNOWN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeAsByteBuf(ChannelBuffer buffer) {
|
||||
// NOOP
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoder, decoder and their related message types for Socks.
|
||||
*
|
||||
* Be aware it is only supported on Java 6+.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
593
src/main/java/org/jboss/netty/util/NetUtil.java
Normal file
593
src/main/java/org/jboss/netty/util/NetUtil.java
Normal file
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.util;
|
||||
|
||||
import org.jboss.netty.logging.InternalLogger;
|
||||
import org.jboss.netty.logging.InternalLoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* A class that holds a number of network-related constants.
|
||||
* <p/>
|
||||
* This class borrowed some of its methods from a modified fork of the
|
||||
* <a href="http://svn.apache.org/repos/asf/harmony/enhanced/java/branches/java6/classlib/modules/luni/
|
||||
* src/main/java/org/apache/harmony/luni/util/Inet6Util.java">Inet6Util class</a> which was part of Apache Harmony.
|
||||
*/
|
||||
public final class NetUtil {
|
||||
|
||||
/**
|
||||
* The {@link InetAddress} representing the host machine
|
||||
* <p/>
|
||||
* We cache this because some machines take almost forever to return from
|
||||
* {@link InetAddress}.getLocalHost(). This may be due to incorrect
|
||||
* configuration of the hosts and DNS client configuration files.
|
||||
*/
|
||||
public static final InetAddress LOCALHOST;
|
||||
|
||||
/**
|
||||
* The loopback {@link NetworkInterface} on the current machine
|
||||
*/
|
||||
public static final NetworkInterface LOOPBACK_IF;
|
||||
|
||||
/**
|
||||
* The SOMAXCONN value of the current machine. If failed to get the value, 3072 is used as a
|
||||
* default value.
|
||||
*/
|
||||
public static final int SOMAXCONN;
|
||||
|
||||
/**
|
||||
* The logger being used by this class
|
||||
*/
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(NetUtil.class);
|
||||
|
||||
static {
|
||||
//Start the process of discovering localhost
|
||||
InetAddress localhost;
|
||||
try {
|
||||
localhost = InetAddress.getLocalHost();
|
||||
validateHost(localhost);
|
||||
} catch (IOException e) {
|
||||
// The default local host names did not work. Try hard-coded IPv4 address.
|
||||
try {
|
||||
localhost = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
|
||||
validateHost(localhost);
|
||||
} catch (IOException e1) {
|
||||
// The hard-coded IPv4 address did not work. Try hard coded IPv6 address.
|
||||
try {
|
||||
localhost = InetAddress.getByAddress(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1});
|
||||
validateHost(localhost);
|
||||
} catch (IOException e2) {
|
||||
throw new Error("Failed to resolve localhost - incorrect network configuration?", e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOCALHOST = localhost;
|
||||
|
||||
//Prepare to get the local NetworkInterface
|
||||
NetworkInterface loopbackInterface;
|
||||
|
||||
try {
|
||||
//Automatically get the loopback interface
|
||||
loopbackInterface = NetworkInterface.getByInetAddress(LOCALHOST);
|
||||
} catch (SocketException e) {
|
||||
//No? Alright. There is a backup!
|
||||
loopbackInterface = null;
|
||||
}
|
||||
|
||||
//Check to see if a network interface was not found
|
||||
if (loopbackInterface == null) {
|
||||
try {
|
||||
//Start iterating over all network interfaces
|
||||
for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
interfaces.hasMoreElements();) {
|
||||
//Get the "next" interface
|
||||
NetworkInterface networkInterface = interfaces.nextElement();
|
||||
|
||||
//Check to see if the interface is a loopback interface
|
||||
if (networkInterface.isLoopback()) {
|
||||
//Phew! The loopback interface was found.
|
||||
loopbackInterface = networkInterface;
|
||||
//No need to keep iterating
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
//Nope. Can't do anything else, sorry!
|
||||
logger.error("Failed to enumerate network interfaces", e);
|
||||
}
|
||||
}
|
||||
|
||||
//Set the loopback interface constant
|
||||
LOOPBACK_IF = loopbackInterface;
|
||||
|
||||
int somaxconn = 3072;
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
in = new BufferedReader(new FileReader("/proc/sys/net/core/somaxconn"));
|
||||
somaxconn = Integer.parseInt(in.readLine());
|
||||
} catch (Exception e) {
|
||||
// Failed to get SOMAXCONN
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
// Ignored.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SOMAXCONN = somaxconn;
|
||||
}
|
||||
|
||||
private static void validateHost(InetAddress host) throws IOException {
|
||||
ServerSocket ss = null;
|
||||
Socket s1 = null;
|
||||
Socket s2 = null;
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.setReuseAddress(false);
|
||||
ss.bind(new InetSocketAddress(host, 0));
|
||||
s1 = new Socket(host, ss.getLocalPort());
|
||||
s2 = ss.accept();
|
||||
} finally {
|
||||
if (s2 != null) {
|
||||
try {
|
||||
s2.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
if (s1 != null) {
|
||||
try {
|
||||
s1.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
if (ss != null) {
|
||||
try {
|
||||
ss.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an byte[] based on an ipAddressString. No error handling is
|
||||
* performed here.
|
||||
*/
|
||||
public static byte[] createByteArrayFromIpAddressString(
|
||||
String ipAddressString) {
|
||||
|
||||
if (isValidIpV4Address(ipAddressString)) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(ipAddressString,
|
||||
".");
|
||||
String token;
|
||||
int tempInt;
|
||||
byte[] byteAddress = new byte[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
token = tokenizer.nextToken();
|
||||
tempInt = Integer.parseInt(token);
|
||||
byteAddress[i] = (byte) tempInt;
|
||||
}
|
||||
|
||||
return byteAddress;
|
||||
}
|
||||
|
||||
if (isValidIpV6Address(ipAddressString)) {
|
||||
if (ipAddressString.charAt(0) == '[') {
|
||||
ipAddressString = ipAddressString.substring(1, ipAddressString
|
||||
.length() - 1);
|
||||
}
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(ipAddressString, ":.",
|
||||
true);
|
||||
ArrayList<String> hexStrings = new ArrayList<String>();
|
||||
ArrayList<String> decStrings = new ArrayList<String>();
|
||||
String token = "";
|
||||
String prevToken = "";
|
||||
int doubleColonIndex = -1; // If a double colon exists, we need to
|
||||
// insert 0s.
|
||||
|
||||
// Go through the tokens, including the seperators ':' and '.'
|
||||
// When we hit a : or . the previous token will be added to either
|
||||
// the hex list or decimal list. In the case where we hit a ::
|
||||
// we will save the index of the hexStrings so we can add zeros
|
||||
// in to fill out the string
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
prevToken = token;
|
||||
token = tokenizer.nextToken();
|
||||
|
||||
if (":".equals(token)) {
|
||||
if (":".equals(prevToken)) {
|
||||
doubleColonIndex = hexStrings.size();
|
||||
} else if (!prevToken.isEmpty()) {
|
||||
hexStrings.add(prevToken);
|
||||
}
|
||||
} else if (".".equals(token)) {
|
||||
decStrings.add(prevToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (":".equals(prevToken)) {
|
||||
if (":".equals(token)) {
|
||||
doubleColonIndex = hexStrings.size();
|
||||
} else {
|
||||
hexStrings.add(token);
|
||||
}
|
||||
} else if (".".equals(prevToken)) {
|
||||
decStrings.add(token);
|
||||
}
|
||||
|
||||
// figure out how many hexStrings we should have
|
||||
// also check if it is a IPv4 address
|
||||
int hexStringsLength = 8;
|
||||
|
||||
// If we have an IPv4 address tagged on at the end, subtract
|
||||
// 4 bytes, or 2 hex words from the total
|
||||
if (!decStrings.isEmpty()) {
|
||||
hexStringsLength -= 2;
|
||||
}
|
||||
|
||||
// if we hit a double Colon add the appropriate hex strings
|
||||
if (doubleColonIndex != -1) {
|
||||
int numberToInsert = hexStringsLength - hexStrings.size();
|
||||
for (int i = 0; i < numberToInsert; i++) {
|
||||
hexStrings.add(doubleColonIndex, "0");
|
||||
}
|
||||
}
|
||||
|
||||
byte[] ipByteArray = new byte[16];
|
||||
|
||||
// Finally convert these strings to bytes...
|
||||
for (int i = 0; i < hexStrings.size(); i++) {
|
||||
convertToBytes(hexStrings.get(i), ipByteArray, i * 2);
|
||||
}
|
||||
|
||||
// Now if there are any decimal values, we know where they go...
|
||||
for (int i = 0; i < decStrings.size(); i++) {
|
||||
ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings
|
||||
.get(i)) & 255);
|
||||
}
|
||||
return ipByteArray;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a 4 character hex word into a 2 byte word equivalent
|
||||
*/
|
||||
private static void convertToBytes(String hexWord, byte[] ipByteArray,
|
||||
int byteIndex) {
|
||||
|
||||
int hexWordLength = hexWord.length();
|
||||
int hexWordIndex = 0;
|
||||
ipByteArray[byteIndex] = 0;
|
||||
ipByteArray[byteIndex + 1] = 0;
|
||||
int charValue;
|
||||
|
||||
// high order 4 bits of first byte
|
||||
if (hexWordLength > 3) {
|
||||
charValue = getIntValue(hexWord.charAt(hexWordIndex++));
|
||||
ipByteArray[byteIndex] |= charValue << 4;
|
||||
}
|
||||
|
||||
// low order 4 bits of the first byte
|
||||
if (hexWordLength > 2) {
|
||||
charValue = getIntValue(hexWord.charAt(hexWordIndex++));
|
||||
ipByteArray[byteIndex] |= charValue;
|
||||
}
|
||||
|
||||
// high order 4 bits of second byte
|
||||
if (hexWordLength > 1) {
|
||||
charValue = getIntValue(hexWord.charAt(hexWordIndex++));
|
||||
ipByteArray[byteIndex + 1] |= charValue << 4;
|
||||
}
|
||||
|
||||
// low order 4 bits of the first byte
|
||||
charValue = getIntValue(hexWord.charAt(hexWordIndex));
|
||||
ipByteArray[byteIndex + 1] |= charValue & 15;
|
||||
}
|
||||
|
||||
static int getIntValue(char c) {
|
||||
|
||||
switch (c) {
|
||||
case '0':
|
||||
return 0;
|
||||
case '1':
|
||||
return 1;
|
||||
case '2':
|
||||
return 2;
|
||||
case '3':
|
||||
return 3;
|
||||
case '4':
|
||||
return 4;
|
||||
case '5':
|
||||
return 5;
|
||||
case '6':
|
||||
return 6;
|
||||
case '7':
|
||||
return 7;
|
||||
case '8':
|
||||
return 8;
|
||||
case '9':
|
||||
return 9;
|
||||
}
|
||||
|
||||
c = Character.toLowerCase(c);
|
||||
switch (c) {
|
||||
case 'a':
|
||||
return 10;
|
||||
case 'b':
|
||||
return 11;
|
||||
case 'c':
|
||||
return 12;
|
||||
case 'd':
|
||||
return 13;
|
||||
case 'e':
|
||||
return 14;
|
||||
case 'f':
|
||||
return 15;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static boolean isValidIpV6Address(String ipAddress) {
|
||||
int length = ipAddress.length();
|
||||
boolean doubleColon = false;
|
||||
int numberOfColons = 0;
|
||||
int numberOfPeriods = 0;
|
||||
int numberOfPercent = 0;
|
||||
StringBuilder word = new StringBuilder();
|
||||
char c = 0;
|
||||
char prevChar;
|
||||
int offset = 0; // offset for [] ip addresses
|
||||
|
||||
if (length < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
prevChar = c;
|
||||
c = ipAddress.charAt(i);
|
||||
switch (c) {
|
||||
|
||||
// case for an open bracket [x:x:x:...x]
|
||||
case '[':
|
||||
if (i != 0) {
|
||||
return false; // must be first character
|
||||
}
|
||||
if (ipAddress.charAt(length - 1) != ']') {
|
||||
return false; // must have a close ]
|
||||
}
|
||||
offset = 1;
|
||||
if (length < 4) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
// case for a closed bracket at end of IP [x:x:x:...x]
|
||||
case ']':
|
||||
if (i != length - 1) {
|
||||
return false; // must be last charcter
|
||||
}
|
||||
if (ipAddress.charAt(0) != '[') {
|
||||
return false; // must have a open [
|
||||
}
|
||||
break;
|
||||
|
||||
// case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d
|
||||
case '.':
|
||||
numberOfPeriods++;
|
||||
if (numberOfPeriods > 3) {
|
||||
return false;
|
||||
}
|
||||
if (!isValidIp4Word(word.toString())) {
|
||||
return false;
|
||||
}
|
||||
if (numberOfColons != 6 && !doubleColon) {
|
||||
return false;
|
||||
}
|
||||
// a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an
|
||||
// IPv4 ending, otherwise 7 :'s is bad
|
||||
if (numberOfColons == 7 && ipAddress.charAt(offset) != ':'
|
||||
&& ipAddress.charAt(1 + offset) != ':') {
|
||||
return false;
|
||||
}
|
||||
word.delete(0, word.length());
|
||||
break;
|
||||
|
||||
case ':':
|
||||
// FIX "IP6 mechanism syntax #ip6-bad1"
|
||||
// An IPV6 address cannot start with a single ":".
|
||||
// Either it can starti with "::" or with a number.
|
||||
if (i == offset && (ipAddress.length() <= i || ipAddress.charAt(i + 1) != ':')) {
|
||||
return false;
|
||||
}
|
||||
// END FIX "IP6 mechanism syntax #ip6-bad1"
|
||||
numberOfColons++;
|
||||
if (numberOfColons > 7) {
|
||||
return false;
|
||||
}
|
||||
if (numberOfPeriods > 0) {
|
||||
return false;
|
||||
}
|
||||
if (prevChar == ':') {
|
||||
if (doubleColon) {
|
||||
return false;
|
||||
}
|
||||
doubleColon = true;
|
||||
}
|
||||
word.delete(0, word.length());
|
||||
break;
|
||||
case '%':
|
||||
if (numberOfColons == 0) {
|
||||
return false;
|
||||
}
|
||||
numberOfPercent++;
|
||||
|
||||
// validate that the stuff after the % is valid
|
||||
if (i + 1 >= length) {
|
||||
// in this case the percent is there but no number is
|
||||
// available
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Integer.parseInt(ipAddress.substring(i + 1));
|
||||
} catch (NumberFormatException e) {
|
||||
// right now we just support an integer after the % so if
|
||||
// this is not
|
||||
// what is there then return
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (numberOfPercent == 0) {
|
||||
if (word != null && word.length() > 3) {
|
||||
return false;
|
||||
}
|
||||
if (!isValidHexChar(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
word.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have an IPv4 ending
|
||||
if (numberOfPeriods > 0) {
|
||||
// There is a test case with 7 colons and valid ipv4 this should resolve it
|
||||
if (numberOfPeriods != 3 || !(isValidIp4Word(word.toString()) && numberOfColons < 7)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// If we're at then end and we haven't had 7 colons then there is a
|
||||
// problem unless we encountered a doubleColon
|
||||
if (numberOfColons != 7 && !doubleColon) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we have an empty word at the end, it means we ended in either
|
||||
// a : or a .
|
||||
// If we did not end in :: then this is invalid
|
||||
if (numberOfPercent == 0) {
|
||||
if (word.length() == 0 && ipAddress.charAt(length - 1 - offset) == ':'
|
||||
&& ipAddress.charAt(length - 2 - offset) != ':') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isValidIp4Word(String word) {
|
||||
char c;
|
||||
if (word.length() < 1 || word.length() > 3) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < word.length(); i++) {
|
||||
c = word.charAt(i);
|
||||
if (!(c >= '0' && c <= '9')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (Integer.parseInt(word) > 255) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean isValidHexChar(char c) {
|
||||
return c >= '0' && c <= '9' || c >= 'A' && c <= 'F'
|
||||
|| c >= 'a' && c <= 'f';
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a string and parses it to see if it is a valid IPV4 address.
|
||||
*
|
||||
* @return true, if the string represents an IPV4 address in dotted
|
||||
* notation, false otherwise
|
||||
*/
|
||||
public static boolean isValidIpV4Address(String value) {
|
||||
|
||||
int periods = 0;
|
||||
int i;
|
||||
int length = value.length();
|
||||
|
||||
if (length > 15) {
|
||||
return false;
|
||||
}
|
||||
char c;
|
||||
StringBuilder word = new StringBuilder();
|
||||
for (i = 0; i < length; i++) {
|
||||
c = value.charAt(i);
|
||||
if (c == '.') {
|
||||
periods++;
|
||||
if (periods > 3) {
|
||||
return false;
|
||||
}
|
||||
if (word.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
if (Integer.parseInt(word.toString()) > 255) {
|
||||
return false;
|
||||
}
|
||||
word.delete(0, word.length());
|
||||
} else if (!Character.isDigit(c)) {
|
||||
return false;
|
||||
} else {
|
||||
if (word.length() > 2) {
|
||||
return false;
|
||||
}
|
||||
word.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (word.length() == 0 || Integer.parseInt(word.toString()) > 255) {
|
||||
return false;
|
||||
}
|
||||
if (periods != 3) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructor to stop this class being constructed.
|
||||
*/
|
||||
private NetUtil() {
|
||||
// Unused
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SocksAuthRequestDecoderTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SocksAuthRequestDecoderTest.class);
|
||||
@Test
|
||||
public void testAuthRequestDecoder() throws Exception{
|
||||
String username = "test";
|
||||
String password = "test";
|
||||
SocksAuthRequest msg = new SocksAuthRequest(username, password);
|
||||
SocksAuthRequestDecoder decoder = new SocksAuthRequestDecoder();
|
||||
DecoderEmbedder<SocksAuthRequest> embedder = new DecoderEmbedder<SocksAuthRequest>(decoder);
|
||||
SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg);
|
||||
msg = embedder.poll();
|
||||
assertEquals(msg.getUsername(), username);
|
||||
assertEquals(msg.getUsername(), password);
|
||||
assertNull(embedder.poll());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SocksAuthRequestTest {
|
||||
@Test
|
||||
public void testConstructorParamsAreNotNull() {
|
||||
try {
|
||||
new SocksAuthRequest(null, "");
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
try {
|
||||
new SocksAuthRequest("", null);
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsernameOrPasswordIsNotAscii() {
|
||||
try {
|
||||
new SocksAuthRequest("παράδειγμα.δοκιμή", "password");
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
try {
|
||||
new SocksAuthRequest("username", "παράδειγμα.δοκιμή");
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsernameOrPasswordLengthIsLessThan255Chars() {
|
||||
try {
|
||||
new SocksAuthRequest(
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword",
|
||||
"password");
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
try {
|
||||
new SocksAuthRequest("password",
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword" +
|
||||
"passwordpasswordpasswordpasswordpasswordpasswordpassword");
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SocksAuthResponseDecoderTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SocksAuthResponseDecoderTest.class);
|
||||
private static void testSocksAuthResponseDecoderWithDifferentParams(SocksMessage.AuthStatus authStatus)
|
||||
throws Exception{
|
||||
logger.debug("Testing SocksAuthResponseDecoder with authStatus: "+ authStatus);
|
||||
SocksAuthResponse msg = new SocksAuthResponse(authStatus);
|
||||
SocksAuthResponseDecoder decoder = new SocksAuthResponseDecoder();
|
||||
DecoderEmbedder<SocksAuthResponse> embedder = new DecoderEmbedder<SocksAuthResponse>(decoder);
|
||||
SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg);
|
||||
msg = embedder.poll();
|
||||
assertSame(msg.getAuthStatus(), authStatus);
|
||||
assertNull(embedder.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSocksCmdResponseDecoder() throws Exception {
|
||||
for (SocksMessage.AuthStatus authStatus: SocksMessage.AuthStatus.values()) {
|
||||
testSocksAuthResponseDecoderWithDifferentParams(authStatus);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SocksAuthResponseTest {
|
||||
@Test
|
||||
public void testConstructorParamsAreNotNull() {
|
||||
try {
|
||||
new SocksAuthResponse(null);
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SocksCmdRequestDecoderTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SocksCmdRequestDecoderTest.class);
|
||||
|
||||
private static void testSocksCmdRequestDecoderWithDifferentParams(SocksMessage.CmdType cmdType,
|
||||
SocksMessage.AddressType addressType, String host, int port) throws Exception {
|
||||
logger.debug("Testing cmdType: " + cmdType + " addressType: " + addressType + " host: "
|
||||
+ host + " port: " + port);
|
||||
SocksCmdRequest msg = new SocksCmdRequest(cmdType, addressType, host, port);
|
||||
SocksCmdRequestDecoder decoder = new SocksCmdRequestDecoder();
|
||||
DecoderEmbedder<SocksRequest> embedder = new DecoderEmbedder<SocksRequest>(decoder);
|
||||
SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg);
|
||||
if (msg.getAddressType() == SocksMessage.AddressType.UNKNOWN) {
|
||||
assertTrue(embedder.poll() instanceof UnknownSocksRequest);
|
||||
} else {
|
||||
msg = (SocksCmdRequest) embedder.poll();
|
||||
assertSame(msg.getCmdType(), cmdType);
|
||||
assertSame(msg.getAddressType(), addressType);
|
||||
assertEquals(msg.getHost(), host);
|
||||
assertEquals(msg.getPort(), port);
|
||||
}
|
||||
assertNull(embedder.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCmdRequestDecoderIPv4() throws Exception{
|
||||
String[] hosts = { "127.0.0.1" };
|
||||
int[] ports = {0, 32769, 65535 };
|
||||
for (SocksMessage.CmdType cmdType : SocksMessage.CmdType.values()) {
|
||||
for (String host : hosts) {
|
||||
for (int port : ports) {
|
||||
testSocksCmdRequestDecoderWithDifferentParams(cmdType, SocksMessage.AddressType.IPv4, host, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCmdRequestDecoderIPv6() throws Exception{
|
||||
String[] hosts = { SocksCommonUtils.ipv6toStr(IPAddressUtil.textToNumericFormatV6("::1")) };
|
||||
int[] ports = {0, 32769, 65535};
|
||||
for (SocksMessage.CmdType cmdType : SocksMessage.CmdType.values()) {
|
||||
for (String host : hosts) {
|
||||
for (int port : ports) {
|
||||
testSocksCmdRequestDecoderWithDifferentParams(cmdType, SocksMessage.AddressType.IPv6, host, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCmdRequestDecoderDomain() throws Exception{
|
||||
String[] hosts = {"google.com" ,
|
||||
"مثال.إختبار",
|
||||
"παράδειγμα.δοκιμή",
|
||||
"مثال.آزمایشی",
|
||||
"пример.испытание",
|
||||
"בײַשפּיל.טעסט",
|
||||
"例子.测试",
|
||||
"例子.測試",
|
||||
"उदाहरण.परीक्षा",
|
||||
"例え.テスト",
|
||||
"실례.테스트",
|
||||
"உதாரணம்.பரிட்சை"};
|
||||
int[] ports = {0, 32769, 65535};
|
||||
for (SocksMessage.CmdType cmdType : SocksMessage.CmdType.values()) {
|
||||
for (String host : hosts) {
|
||||
for (int port : ports) {
|
||||
testSocksCmdRequestDecoderWithDifferentParams(cmdType, SocksMessage.AddressType.DOMAIN, host, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCmdRequestDecoderUnknown() throws Exception{
|
||||
String host = "google.com";
|
||||
int port = 80;
|
||||
for (SocksMessage.CmdType cmdType : SocksMessage.CmdType.values()) {
|
||||
testSocksCmdRequestDecoderWithDifferentParams(cmdType, SocksMessage.AddressType.UNKNOWN, host, port);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SocksCmdRequestTest {
|
||||
@Test
|
||||
public void testConstructorParamsAreNotNull(){
|
||||
try {
|
||||
new SocksCmdRequest(null, SocksMessage.AddressType.UNKNOWN, "", 0);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
|
||||
try {
|
||||
new SocksCmdRequest(SocksMessage.CmdType.UNKNOWN, null, "", 0);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
|
||||
try {
|
||||
new SocksCmdRequest(SocksMessage.CmdType.UNKNOWN, SocksMessage.AddressType.UNKNOWN, null, 0);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv4CorrectAddress(){
|
||||
try {
|
||||
new SocksCmdRequest(SocksMessage.CmdType.BIND, SocksMessage.AddressType.IPv4, "54.54.1111.253", 0);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv6CorrectAddress(){
|
||||
try {
|
||||
new SocksCmdRequest(SocksMessage.CmdType.BIND, SocksMessage.AddressType.IPv6, "xxx:xxx:xxx", 0);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIDNNotExceeds255CharsLimit(){
|
||||
try {
|
||||
new SocksCmdRequest(SocksMessage.CmdType.BIND, SocksMessage.AddressType.DOMAIN,
|
||||
"παράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμή" +
|
||||
"παράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμή" +
|
||||
"παράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμή" +
|
||||
"παράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμήπαράδειγμα.δοκιμή", 0);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPortRange(){
|
||||
try {
|
||||
new SocksCmdRequest(SocksMessage.CmdType.BIND, SocksMessage.AddressType.DOMAIN,
|
||||
"παράδειγμα.δοκιμήπαράδει", -1);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
|
||||
try {
|
||||
new SocksCmdRequest(SocksMessage.CmdType.BIND, SocksMessage.AddressType.DOMAIN,
|
||||
"παράδειγμα.δοκιμήπαράδει", 65536);
|
||||
} catch (Exception e){
|
||||
assertTrue(e instanceof IllegalArgumentException);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SocksCmdResponseDecoderTest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SocksCmdResponseDecoderTest.class);
|
||||
|
||||
private static void testSocksCmdResponseDecoderWithDifferentParams(SocksMessage.CmdStatus cmdStatus,
|
||||
SocksMessage.AddressType addressType) throws Exception {
|
||||
logger.debug("Testing cmdStatus: " + cmdStatus + " addressType: " + addressType);
|
||||
SocksResponse msg = new SocksCmdResponse(cmdStatus, addressType);
|
||||
SocksCmdResponseDecoder decoder = new SocksCmdResponseDecoder();
|
||||
DecoderEmbedder<SocksResponse> embedder = new DecoderEmbedder<SocksResponse>(decoder);
|
||||
SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg);
|
||||
if (addressType == SocksMessage.AddressType.UNKNOWN) {
|
||||
assertTrue(embedder.poll() instanceof UnknownSocksResponse);
|
||||
} else {
|
||||
msg = embedder.poll();
|
||||
assertEquals(((SocksCmdResponse) msg).getCmdStatus(), cmdStatus);
|
||||
}
|
||||
assertNull(embedder.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSocksCmdResponseDecoder() throws Exception {
|
||||
for (SocksMessage.CmdStatus cmdStatus: SocksMessage.CmdStatus.values()) {
|
||||
for (SocksMessage.AddressType addressType: SocksMessage.AddressType.values()) {
|
||||
testSocksCmdResponseDecoderWithDifferentParams(cmdStatus, addressType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SocksCmdResponseTest {
|
||||
@Test
|
||||
public void testConstructorParamsAreNotNull() {
|
||||
try {
|
||||
new SocksCmdResponse(null, SocksMessage.AddressType.UNKNOWN);
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
try {
|
||||
new SocksCmdResponse(SocksMessage.CmdStatus.UNASSIGNED, null);
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.handler.codec.embedder.DecoderEmbedder;
|
||||
|
||||
final class SocksCommonTestUtils {
|
||||
private static final int DEFAULT_ENCODER_BUFFER_SIZE = 1024;
|
||||
/**
|
||||
* A constructor to stop this class being constructed.
|
||||
*/
|
||||
private SocksCommonTestUtils() {
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public static void writeMessageIntoEmbedder(DecoderEmbedder embedder, SocksMessage msg)
|
||||
throws Exception {
|
||||
ChannelBuffer buf = ChannelBuffers.buffer(DEFAULT_ENCODER_BUFFER_SIZE);
|
||||
msg.encodeAsByteBuf(buf);
|
||||
embedder.offer(buf);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SocksInitRequestTest {
|
||||
@Test
|
||||
public void testConstructorParamsAreNotNull() {
|
||||
try {
|
||||
new SocksInitRequest(null);
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.socks;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SocksInitResponseTest {
|
||||
@Test
|
||||
public void testConstructorParamsAreNotNull() {
|
||||
try {
|
||||
new SocksInitResponse(null);
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof NullPointerException);
|
||||
}
|
||||
}
|
||||
}
|
297
src/test/java/org/jboss/netty/util/NetUtilTest.java
Normal file
297
src/test/java/org/jboss/netty/util/NetUtilTest.java
Normal file
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jboss.netty.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class NetUtilTest {
|
||||
private final static Map<String, byte[]> validIpV4Hosts = new HashMap<String, byte[]>() {
|
||||
private static final long serialVersionUID = 2629792739366724032L;
|
||||
{
|
||||
put("192.168.1.0", new byte[]{
|
||||
(byte) 0xc0, (byte) 0xa8, 0x01, 0x00}
|
||||
);
|
||||
put("10.255.255.254", new byte[]{
|
||||
0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xfe
|
||||
});
|
||||
put("172.18.5.4", new byte[]{
|
||||
(byte) 0xac, 0x12, 0x05, 0x04
|
||||
});
|
||||
put("0.0.0.0", new byte[]{
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
});
|
||||
put("127.0.0.1", new byte[]{
|
||||
0x7f, 0x00, 0x00, 0x01
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
private final static Map<String, byte[]> invalidIpV4Hosts = new HashMap<String, byte[]>() {
|
||||
private static final long serialVersionUID = 1299215199895717282L;
|
||||
{
|
||||
put("1.256.3.4", null);
|
||||
put("256.0.0.1", null);
|
||||
put("1.1.1.1.1", null);
|
||||
}
|
||||
};
|
||||
private final static Map<String, byte[]> validIpV6Hosts = new HashMap<String, byte[]>() {
|
||||
private static final long serialVersionUID = 3999763170377573184L;
|
||||
{
|
||||
put("::ffff:5.6.7.8", new byte[]{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, (byte) 0xff, (byte) 0xff,
|
||||
0x05, 0x06, 0x07, 0x08}
|
||||
);
|
||||
put("fdf8:f53b:82e4::53", new byte[]{
|
||||
(byte) 0xfd, (byte) 0xf8, (byte) 0xf5, 0x3b,
|
||||
(byte) 0x82, (byte) 0xe4, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x53}
|
||||
);
|
||||
put("fe80::200:5aee:feaa:20a2", new byte[]{
|
||||
(byte) 0xfe, (byte) 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x5a, (byte) 0xee,
|
||||
(byte) 0xfe, (byte) 0xaa, 0x20, (byte) 0xa2}
|
||||
);
|
||||
put("2001::1", new byte[]{
|
||||
0x20, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01}
|
||||
);
|
||||
put("2001:0000:4136:e378:8000:63bf:3fff:fdd2", new byte[]{
|
||||
0x20, 0x01, 0x00, 0x00,
|
||||
0x41, 0x36, (byte) 0xe3, 0x78,
|
||||
(byte) 0x80, 0x00, 0x63, (byte) 0xbf,
|
||||
0x3f, (byte) 0xff, (byte) 0xfd, (byte) 0xd2}
|
||||
);
|
||||
put("2001:0002:6c::430", new byte[]{
|
||||
0x20, 0x01, 0x00, 0x02,
|
||||
0x00, 0x6c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x04, 0x30}
|
||||
);
|
||||
put("2001:10:240:ab::a", new byte[]{
|
||||
0x20, 0x01, 0x00, 0x10,
|
||||
0x02, 0x40, 0x00, (byte) 0xab,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0a});
|
||||
put("2002:cb0a:3cdd:1::1", new byte[]{
|
||||
0x20, 0x02, (byte) 0xcb, 0x0a,
|
||||
0x3c, (byte) 0xdd, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01}
|
||||
);
|
||||
put("2001:db8:8:4::2", new byte[]{
|
||||
0x20, 0x01, 0x0d, (byte) 0xb8,
|
||||
0x00, 0x08, 0x00, 0x04,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02}
|
||||
);
|
||||
put("ff01:0:0:0:0:0:0:2", new byte[]{
|
||||
(byte) 0xff, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02}
|
||||
);
|
||||
put("[fdf8:f53b:82e4::53]", new byte[]{
|
||||
(byte) 0xfd, (byte) 0xf8, (byte) 0xf5, 0x3b,
|
||||
(byte) 0x82, (byte) 0xe4, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x53}
|
||||
);
|
||||
put("[fe80::200:5aee:feaa:20a2]", new byte[]{
|
||||
(byte) 0xfe, (byte) 0x80, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x5a, (byte) 0xee,
|
||||
(byte) 0xfe, (byte) 0xaa, 0x20, (byte) 0xa2}
|
||||
);
|
||||
put("[2001::1]", new byte[]{
|
||||
0x20, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01}
|
||||
);
|
||||
put("[2001:0000:4136:e378:8000:63bf:3fff:fdd2]", new byte[]{
|
||||
0x20, 0x01, 0x00, 0x00,
|
||||
0x41, 0x36, (byte) 0xe3, 0x78,
|
||||
(byte) 0x80, 0x00, 0x63, (byte) 0xbf,
|
||||
0x3f, (byte) 0xff, (byte) 0xfd, (byte) 0xd2}
|
||||
);
|
||||
put("0:1:2:3:4:5:6:789a", new byte[]{
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x02, 0x00, 0x03,
|
||||
0x00, 0x04, 0x00, 0x05,
|
||||
0x00, 0x06, 0x78, (byte) 0x9a}
|
||||
);
|
||||
put("0:1:2:3::f", new byte[]{
|
||||
0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x02, 0x00, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0f}
|
||||
);
|
||||
put("0:0:0:0:0:0:10.0.0.1", new byte[]{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x01}
|
||||
);
|
||||
put("::ffff:192.168.0.1", new byte[]{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, (byte) 0xff, (byte) 0xff,
|
||||
(byte) 0xc0, (byte) 0xa8, 0x00, 0x01}
|
||||
);
|
||||
}
|
||||
};
|
||||
private final static Map<String, byte[]> invalidIpV6Hosts = new HashMap<String, byte[]>() {
|
||||
private static final long serialVersionUID = -5870810805409009696L;
|
||||
{
|
||||
// Test method with garbage.
|
||||
put("Obvious Garbage", null);
|
||||
// Test method with preferred style, too many :
|
||||
put("0:1:2:3:4:5:6:7:8", null);
|
||||
// Test method with preferred style, not enough :
|
||||
put("0:1:2:3:4:5:6", null);
|
||||
// Test method with preferred style, bad digits.
|
||||
put("0:1:2:3:4:5:6:x", null);
|
||||
// Test method with preferred style, adjacent :
|
||||
put("0:1:2:3:4:5:6::7", null);
|
||||
// Test method with preferred style, too many digits.
|
||||
put("0:1:2:3:4:5:6:789abcdef", null);
|
||||
// Test method with compressed style, bad digits.
|
||||
put("0:1:2:3::x", null);
|
||||
// Test method with compressed style, too many adjacent :
|
||||
put("0:1:2:::3", null);
|
||||
// Test method with compressed style, too many digits.
|
||||
put("0:1:2:3::abcde", null);
|
||||
// Test method with preferred style, too many :
|
||||
put("0:1:2:3:4:5:6:7:8", null);
|
||||
// Test method with compressed style, not enough :
|
||||
put("0:1", null);
|
||||
// Test method with ipv4 style, bad ipv6 digits.
|
||||
put("0:0:0:0:0:x:10.0.0.1", null);
|
||||
// Test method with ipv4 style, bad ipv4 digits.
|
||||
put("0:0:0:0:0:0:10.0.0.x", null);
|
||||
// Test method with ipv4 style, adjacent :
|
||||
put("0:0:0:0:0::0:10.0.0.1", null);
|
||||
// Test method with ipv4 style, too many ipv6 digits.
|
||||
put("0:0:0:0:0:00000:10.0.0.1", null);
|
||||
// Test method with ipv4 style, too many :
|
||||
put("0:0:0:0:0:0:0:10.0.0.1", null);
|
||||
// Test method with ipv4 style, not enough :
|
||||
put("0:0:0:0:0:10.0.0.1", null);
|
||||
// Test method with ipv4 style, too many .
|
||||
put("0:0:0:0:0:0:10.0.0.0.1", null);
|
||||
// Test method with ipv4 style, not enough .
|
||||
put("0:0:0:0:0:0:10.0.1", null);
|
||||
// Test method with ipv4 style, adjacent .
|
||||
put("0:0:0:0:0:0:10..0.0.1", null);
|
||||
// Test method with compressed ipv4 style, bad ipv6 digits.
|
||||
put("::fffx:192.168.0.1", null);
|
||||
// Test method with compressed ipv4 style, bad ipv4 digits.
|
||||
put("::ffff:192.168.0.x", null);
|
||||
// Test method with compressed ipv4 style, too many adjacent :
|
||||
put(":::ffff:192.168.0.1", null);
|
||||
// Test method with compressed ipv4 style, too many ipv6 digits.
|
||||
put("::fffff:192.168.0.1", null);
|
||||
// Test method with compressed ipv4 style, too many ipv4 digits.
|
||||
put("::ffff:1923.168.0.1", null);
|
||||
// Test method with compressed ipv4 style, not enough :
|
||||
put(":ffff:192.168.0.1", null);
|
||||
// Test method with compressed ipv4 style, too many .
|
||||
put("::ffff:192.168.0.1.2", null);
|
||||
// Test method with compressed ipv4 style, not enough .
|
||||
put("::ffff:192.168.0", null);
|
||||
// Test method with compressed ipv4 style, adjacent .
|
||||
put("::ffff:192.168..0.1", null);
|
||||
// Test method, garbage.
|
||||
put("absolute, and utter garbage", null);
|
||||
// Test method, bad ipv6 digits.
|
||||
put("x:0:0:0:0:0:10.0.0.1", null);
|
||||
// Test method, bad ipv4 digits.
|
||||
put("0:0:0:0:0:0:x.0.0.1", null);
|
||||
// Test method, too many ipv6 digits.
|
||||
put("00000:0:0:0:0:0:10.0.0.1", null);
|
||||
// Test method, too many ipv4 digits.
|
||||
put("0:0:0:0:0:0:10.0.0.1000", null);
|
||||
// Test method, too many :
|
||||
put("0:0:0:0:0:0:0:10.0.0.1", null);
|
||||
// Test method, not enough :
|
||||
put("0:0:0:0:0:10.0.0.1", null);
|
||||
// Test method, too many .
|
||||
put("0:0:0:0:0:0:10.0.0.0.1", null);
|
||||
// Test method, not enough .
|
||||
put("0:0:0:0:0:0:10.0.1", null);
|
||||
// Test method, adjacent .
|
||||
put("0:0:0:0:0:0:10.0.0..1", null);
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testLocalhost() {
|
||||
assertNotNull(NetUtil.LOCALHOST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoopback() {
|
||||
assertNotNull(NetUtil.LOOPBACK_IF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsValidIpV4Address() {
|
||||
for (String host : validIpV4Hosts.keySet()) {
|
||||
assertTrue(NetUtil.isValidIpV4Address(host));
|
||||
}
|
||||
for (String host : invalidIpV4Hosts.keySet()) {
|
||||
assertFalse(NetUtil.isValidIpV4Address(host));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsValidIpV6Address() {
|
||||
for (String host : validIpV6Hosts.keySet()) {
|
||||
assertTrue(NetUtil.isValidIpV6Address(host));
|
||||
}
|
||||
for (String host : invalidIpV6Hosts.keySet()) {
|
||||
assertFalse(NetUtil.isValidIpV6Address(host));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateByteArrayFromIpAddressString() {
|
||||
for (Entry<String, byte[]> stringEntry : validIpV4Hosts.entrySet()) {
|
||||
assertArrayEquals(stringEntry.getValue(), NetUtil.createByteArrayFromIpAddressString(stringEntry.getKey()));
|
||||
}
|
||||
for (Entry<String, byte[]> stringEntry : invalidIpV4Hosts.entrySet()) {
|
||||
assertArrayEquals(stringEntry.getValue(), NetUtil.createByteArrayFromIpAddressString(stringEntry.getKey()));
|
||||
}
|
||||
for (Entry<String, byte[]> stringEntry : validIpV6Hosts.entrySet()) {
|
||||
assertArrayEquals(stringEntry.getValue(), NetUtil.createByteArrayFromIpAddressString(stringEntry.getKey()));
|
||||
}
|
||||
for (Entry<String, byte[]> stringEntry : invalidIpV6Hosts.entrySet()) {
|
||||
assertArrayEquals(stringEntry.getValue(), NetUtil.createByteArrayFromIpAddressString(stringEntry.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user