Fix the potential copyright issue in SocksCommonUtils
- Add StringUtil.toHexString() methods which are based on LoggingHandler's lookup table implementation, and use it wherever possible
This commit is contained in:
parent
7a1a30f0ad
commit
4a86446053
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.socks;
|
package io.netty.handler.codec.socks;
|
||||||
|
|
||||||
|
import io.netty.util.internal.StringUtil;
|
||||||
|
|
||||||
final class SocksCommonUtils {
|
final class SocksCommonUtils {
|
||||||
public static final SocksRequest UNKNOWN_SOCKS_REQUEST = new UnknownSocksRequest();
|
public static final SocksRequest UNKNOWN_SOCKS_REQUEST = new UnknownSocksRequest();
|
||||||
public static final SocksResponse UNKNOWN_SOCKS_RESPONSE = new UnknownSocksResponse();
|
public static final SocksResponse UNKNOWN_SOCKS_RESPONSE = new UnknownSocksResponse();
|
||||||
@ -41,7 +43,7 @@ final class SocksCommonUtils {
|
|||||||
private static final char[] ipv6conseqZeroFiller = {':', ':'};
|
private static final char[] ipv6conseqZeroFiller = {':', ':'};
|
||||||
private static final char ipv6hextetSeparator = ':';
|
private static final char ipv6hextetSeparator = ':';
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Convert numeric IPv6 to compressed format, where
|
* Convert numeric IPv6 to compressed format, where
|
||||||
* the longest sequence of 0's (with 2 or more 0's) is replaced with "::"
|
* the longest sequence of 0's (with 2 or more 0's) is replaced with "::"
|
||||||
*/
|
*/
|
||||||
@ -77,11 +79,8 @@ final class SocksCommonUtils {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Convert numeric IPv6 to standard (non-compressed) format.
|
* Converts 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) {
|
public static String ipv6toStr(byte[] src) {
|
||||||
assert src.length == 16;
|
assert src.length == 16;
|
||||||
@ -90,14 +89,18 @@ final class SocksCommonUtils {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ipv6toStr(StringBuilder sb, byte[] src,
|
private static void ipv6toStr(StringBuilder sb, byte[] src, int fromHextet, int toHextet) {
|
||||||
int fromHextet, int toHextet) {
|
int i;
|
||||||
for (int i = fromHextet; i < toHextet; i++) {
|
toHextet --;
|
||||||
sb.append(Integer.toHexString(src[i << 1] << 8 & 0xff00
|
for (i = fromHextet; i < toHextet; i++) {
|
||||||
| src[(i << 1) + 1] & 0xff));
|
appendHextet(sb, src, i);
|
||||||
if (i < toHextet - 1) {
|
|
||||||
sb.append(ipv6hextetSeparator);
|
sb.append(ipv6hextetSeparator);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
appendHextet(sb, src, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendHextet(StringBuilder sb, byte[] src, int i) {
|
||||||
|
StringUtil.toHexString(sb, src, i << 1, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,8 @@ public class SocksCmdResponseDecoderTest {
|
|||||||
"testDomain.com", 80);
|
"testDomain.com", 80);
|
||||||
testSocksCmdResponseDecoderWithDifferentParams(cmdStatus, SocksAddressType.IPv6,
|
testSocksCmdResponseDecoderWithDifferentParams(cmdStatus, SocksAddressType.IPv6,
|
||||||
"2001:db8:85a3:42:1000:8a2e:370:7334", 80);
|
"2001:db8:85a3:42:1000:8a2e:370:7334", 80);
|
||||||
|
testSocksCmdResponseDecoderWithDifferentParams(cmdStatus, SocksAddressType.IPv6,
|
||||||
|
"1111:111:11:1:0:0:0:1", 80);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.util.internal;
|
package io.netty.util.internal;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -24,13 +25,14 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class StringUtil {
|
public final class StringUtil {
|
||||||
|
|
||||||
private StringUtil() {
|
|
||||||
// Unused.
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String NEWLINE;
|
public static final String NEWLINE;
|
||||||
|
|
||||||
|
private static final String[] BYTE2HEX_PAD = new String[256];
|
||||||
|
private static final String[] BYTE2HEX_NOPAD = new String[256];
|
||||||
|
private static final String EMPTY_STRING = "";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
// Determine the newline character of the current platform.
|
||||||
String newLine;
|
String newLine;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -41,9 +43,32 @@ public final class StringUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NEWLINE = newLine;
|
NEWLINE = newLine;
|
||||||
}
|
|
||||||
|
|
||||||
private static final String EMPTY_STRING = "";
|
// Generate the lookup table that converts a byte into a 2-digit hexadecimal integer.
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 10; i ++) {
|
||||||
|
StringBuilder buf = new StringBuilder(2);
|
||||||
|
buf.append('0');
|
||||||
|
buf.append(i);
|
||||||
|
BYTE2HEX_PAD[i] = buf.toString();
|
||||||
|
BYTE2HEX_NOPAD[i] = String.valueOf(i);
|
||||||
|
}
|
||||||
|
for (; i < 16; i ++) {
|
||||||
|
StringBuilder buf = new StringBuilder(2);
|
||||||
|
char c = (char) ('a' + i - 10);
|
||||||
|
buf.append('0');
|
||||||
|
buf.append(c);
|
||||||
|
BYTE2HEX_PAD[i] = buf.toString();
|
||||||
|
BYTE2HEX_NOPAD[i] = String.valueOf(c);
|
||||||
|
}
|
||||||
|
for (; i < BYTE2HEX_PAD.length; i ++) {
|
||||||
|
StringBuilder buf = new StringBuilder(2);
|
||||||
|
buf.append(Integer.toHexString(i));
|
||||||
|
String str = buf.toString();
|
||||||
|
BYTE2HEX_PAD[i] = str;
|
||||||
|
BYTE2HEX_NOPAD[i] = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized
|
* Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized
|
||||||
@ -86,6 +111,124 @@ public final class StringUtil {
|
|||||||
return res.toArray(new String[res.size()]);
|
return res.toArray(new String[res.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte value into a 2-digit hexadecimal integer.
|
||||||
|
*/
|
||||||
|
public static String byteToHexStringPadded(int value) {
|
||||||
|
return BYTE2HEX_PAD[value & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte value into a 2-digit hexadecimal integer and appends it to the specified buffer.
|
||||||
|
*/
|
||||||
|
public static <T extends Appendable> T byteToHexStringPadded(T buf, int value) {
|
||||||
|
try {
|
||||||
|
buf.append(byteToHexStringPadded(value));
|
||||||
|
} catch (IOException e) {
|
||||||
|
PlatformDependent.throwException(e);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value.
|
||||||
|
*/
|
||||||
|
public static String toHexStringPadded(byte[] src) {
|
||||||
|
return toHexStringPadded(src, 0, src.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value.
|
||||||
|
*/
|
||||||
|
public static String toHexStringPadded(byte[] src, int offset, int length) {
|
||||||
|
return toHexStringPadded(new StringBuilder(length << 1), src, offset, length).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
|
||||||
|
*/
|
||||||
|
public static <T extends Appendable> T toHexStringPadded(T dst, byte[] src) {
|
||||||
|
return toHexStringPadded(dst, src, 0, src.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
|
||||||
|
*/
|
||||||
|
public static <T extends Appendable> T toHexStringPadded(T dst, byte[] src, int offset, int length) {
|
||||||
|
final int end = offset + length;
|
||||||
|
for (int i = offset; i < end; i ++) {
|
||||||
|
byteToHexStringPadded(dst, src[i]);
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte value into a hexadecimal integer.
|
||||||
|
*/
|
||||||
|
public static String byteToHexString(int value) {
|
||||||
|
return BYTE2HEX_NOPAD[value & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte value into a hexadecimal integer and appends it to the specified buffer.
|
||||||
|
*/
|
||||||
|
public static <T extends Appendable> T byteToHexString(T buf, int value) {
|
||||||
|
try {
|
||||||
|
buf.append(byteToHexString(value));
|
||||||
|
} catch (IOException e) {
|
||||||
|
PlatformDependent.throwException(e);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value.
|
||||||
|
*/
|
||||||
|
public static String toHexString(byte[] src) {
|
||||||
|
return toHexString(src, 0, src.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value.
|
||||||
|
*/
|
||||||
|
public static String toHexString(byte[] src, int offset, int length) {
|
||||||
|
return toHexString(new StringBuilder(length << 1), src, offset, length).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
|
||||||
|
*/
|
||||||
|
public static <T extends Appendable> T toHexString(T dst, byte[] src) {
|
||||||
|
return toHexString(dst, src, 0, src.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
|
||||||
|
*/
|
||||||
|
public static <T extends Appendable> T toHexString(T dst, byte[] src, int offset, int length) {
|
||||||
|
assert length >= 0;
|
||||||
|
if (length == 0) {
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int end = offset + length;
|
||||||
|
final int endMinusOne = end - 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Skip preceding zeroes.
|
||||||
|
for (i = offset; i < endMinusOne; i ++) {
|
||||||
|
if (src[i] != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byteToHexString(dst, src[i ++]);
|
||||||
|
int remaining = end - i;
|
||||||
|
toHexStringPadded(dst, src, i, remaining);
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The shortcut to {@link #simpleClassName(Class) simpleClassName(o.getClass())}.
|
* The shortcut to {@link #simpleClassName(Class) simpleClassName(o.getClass())}.
|
||||||
*/
|
*/
|
||||||
@ -113,4 +256,8 @@ public final class StringUtil {
|
|||||||
return clazz.getName();
|
return clazz.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private StringUtil() {
|
||||||
|
// Unused.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,37 +17,57 @@ package io.netty.util.internal;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static io.netty.util.internal.StringUtil.*;
|
||||||
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class StringUtilTest {
|
public class StringUtilTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensureNewlineExists() {
|
public void ensureNewlineExists() {
|
||||||
assertNotNull(StringUtil.NEWLINE);
|
assertNotNull(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToHexString() {
|
||||||
|
assertThat(toHexString(new byte[] { 0 }), is("0"));
|
||||||
|
assertThat(toHexString(new byte[] { 1 }), is("1"));
|
||||||
|
assertThat(toHexString(new byte[] { 0, 0 }), is("0"));
|
||||||
|
assertThat(toHexString(new byte[] { 1, 0 }), is("100"));
|
||||||
|
assertThat(toHexString(EmptyArrays.EMPTY_BYTES), is(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testToHexStringPadded() {
|
||||||
|
assertThat(toHexStringPadded(new byte[]{0}), is("00"));
|
||||||
|
assertThat(toHexStringPadded(new byte[]{1}), is("01"));
|
||||||
|
assertThat(toHexStringPadded(new byte[]{0, 0}), is("0000"));
|
||||||
|
assertThat(toHexStringPadded(new byte[]{1, 0}), is("0100"));
|
||||||
|
assertThat(toHexStringPadded(EmptyArrays.EMPTY_BYTES), is(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void splitSimple() {
|
public void splitSimple() {
|
||||||
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo:bar", ':'));
|
assertArrayEquals(new String[] { "foo", "bar" }, split("foo:bar", ':'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void splitWithTrailingDelimiter() {
|
public void splitWithTrailingDelimiter() {
|
||||||
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo,bar,", ','));
|
assertArrayEquals(new String[] { "foo", "bar" }, split("foo,bar,", ','));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void splitWithTrailingDelimiters() {
|
public void splitWithTrailingDelimiters() {
|
||||||
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo!bar!!", '!'));
|
assertArrayEquals(new String[] { "foo", "bar" }, split("foo!bar!!", '!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void splitWithConsecutiveDelimiters() {
|
public void splitWithConsecutiveDelimiters() {
|
||||||
assertArrayEquals(new String[] { "foo", "", "bar" }, StringUtil.split("foo$$bar", '$'));
|
assertArrayEquals(new String[] { "foo", "", "bar" }, split("foo$$bar", '$'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void splitWithDelimiterAtBeginning() {
|
public void splitWithDelimiterAtBeginning() {
|
||||||
assertArrayEquals(new String[] { "", "foo", "bar" }, StringUtil.split("#foo#bar", '#'));
|
assertArrayEquals(new String[] { "", "foo", "bar" }, split("#foo#bar", '#'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import io.netty.channel.ChannelHandler.Sharable;
|
|||||||
import io.netty.channel.ChannelHandlerAdapter;
|
import io.netty.channel.ChannelHandlerAdapter;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
|
import io.netty.util.internal.StringUtil;
|
||||||
import io.netty.util.internal.logging.InternalLogLevel;
|
import io.netty.util.internal.logging.InternalLogLevel;
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
import io.netty.util.internal.logging.InternalLogger;
|
||||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||||
@ -50,23 +51,8 @@ public class LoggingHandler extends ChannelHandlerAdapter {
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Generate the lookup table for byte-to-hex-dump conversion
|
// Generate the lookup table for byte-to-hex-dump conversion
|
||||||
for (i = 0; i < 10; i ++) {
|
for (i = 0; i < BYTE2HEX.length; i ++) {
|
||||||
StringBuilder buf = new StringBuilder(3);
|
BYTE2HEX[i] = ' ' + StringUtil.byteToHexStringPadded(i);
|
||||||
buf.append(" 0");
|
|
||||||
buf.append(i);
|
|
||||||
BYTE2HEX[i] = buf.toString();
|
|
||||||
}
|
|
||||||
for (; i < 16; i ++) {
|
|
||||||
StringBuilder buf = new StringBuilder(3);
|
|
||||||
buf.append(" 0");
|
|
||||||
buf.append((char) ('a' + i - 10));
|
|
||||||
BYTE2HEX[i] = buf.toString();
|
|
||||||
}
|
|
||||||
for (; i < BYTE2HEX.length; i ++) {
|
|
||||||
StringBuilder buf = new StringBuilder(3);
|
|
||||||
buf.append(' ');
|
|
||||||
buf.append(Integer.toHexString(i));
|
|
||||||
BYTE2HEX[i] = buf.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the lookup table for hex dump paddings
|
// Generate the lookup table for hex dump paddings
|
||||||
|
Loading…
x
Reference in New Issue
Block a user