Overall refactoring of the haproxy codec
- Convert constant classes to enum - Rename HAProxyProtocolMessage to HAProxyMessage for simpilicity - Rename HAProxyProtocolDecoder to HAProxyMessageDecoder - Rename HAProxyProtocolCommand to HAProxyCommand - Merge ProxiedProtocolAndFamity, ProxiedAddressFamily, and ProxiedTransportProtocol into HAProxiProxiedProtocol and its inner enums - Overall clean-up
This commit is contained in:
parent
8c25830b0b
commit
3900d1c665
@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>io.netty</groupId>
|
<groupId>io.netty</groupId>
|
||||||
<artifactId>netty-parent</artifactId>
|
<artifactId>netty-parent</artifactId>
|
||||||
<version>5.0.0.Alpha2-SNAPSHOT</version>
|
<version>4.1.0.Alpha1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>netty-codec-haproxy</artifactId>
|
<artifactId>netty-codec-haproxy</artifactId>
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command of an HAProxy proxy protocol header
|
||||||
|
*/
|
||||||
|
public enum HAProxyCommand {
|
||||||
|
/**
|
||||||
|
* The LOCAL command represents a connection that was established on purpose by the proxy
|
||||||
|
* without being relayed.
|
||||||
|
*/
|
||||||
|
LOCAL(HAProxyConstants.COMMAND_LOCAL_BYTE),
|
||||||
|
/**
|
||||||
|
* The PROXY command represents a connection that was established on behalf of another node,
|
||||||
|
* and reflects the original connection endpoints.
|
||||||
|
*/
|
||||||
|
PROXY(HAProxyConstants.COMMAND_PROXY_BYTE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command is specified in the lowest 4 bits of the protocol version and command byte
|
||||||
|
*/
|
||||||
|
private static final byte COMMAND_MASK = 0x0f;
|
||||||
|
|
||||||
|
private final byte byteValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*/
|
||||||
|
HAProxyCommand(byte byteValue) {
|
||||||
|
this.byteValue = byteValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link HAProxyCommand} represented by the lowest 4 bits of the specified byte.
|
||||||
|
*
|
||||||
|
* @param verCmdByte protocol version and command byte
|
||||||
|
*/
|
||||||
|
public static HAProxyCommand valueOf(byte verCmdByte) {
|
||||||
|
int cmd = verCmdByte & COMMAND_MASK;
|
||||||
|
switch ((byte) cmd) {
|
||||||
|
case HAProxyConstants.COMMAND_PROXY_BYTE:
|
||||||
|
return PROXY;
|
||||||
|
case HAProxyConstants.COMMAND_LOCAL_BYTE:
|
||||||
|
return LOCAL;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("unknown command: " + cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the byte value of this command.
|
||||||
|
*/
|
||||||
|
public byte byteValue() {
|
||||||
|
return byteValue;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
||||||
|
|
||||||
|
final class HAProxyConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command byte constants
|
||||||
|
*/
|
||||||
|
static final byte COMMAND_LOCAL_BYTE = 0x00;
|
||||||
|
static final byte COMMAND_PROXY_BYTE = 0x01;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version byte constants
|
||||||
|
*/
|
||||||
|
static final byte VERSION_ONE_BYTE = 0x10;
|
||||||
|
static final byte VERSION_TWO_BYTE = 0x20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transport protocol byte constants
|
||||||
|
*/
|
||||||
|
static final byte TRANSPORT_UNSPEC_BYTE = 0x00;
|
||||||
|
static final byte TRANSPORT_STREAM_BYTE = 0x01;
|
||||||
|
static final byte TRANSPORT_DGRAM_BYTE = 0x02;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address family byte constants
|
||||||
|
*/
|
||||||
|
static final byte AF_UNSPEC_BYTE = 0x00;
|
||||||
|
static final byte AF_IPV4_BYTE = 0x10;
|
||||||
|
static final byte AF_IPV6_BYTE = 0x20;
|
||||||
|
static final byte AF_UNIX_BYTE = 0x30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transport protocol and address family byte constants
|
||||||
|
*/
|
||||||
|
static final byte TPAF_UNKNOWN_BYTE = 0x00;
|
||||||
|
static final byte TPAF_TCP4_BYTE = 0x11;
|
||||||
|
static final byte TPAF_TCP6_BYTE = 0x21;
|
||||||
|
static final byte TPAF_UDP4_BYTE = 0x12;
|
||||||
|
static final byte TPAF_UDP6_BYTE = 0x22;
|
||||||
|
static final byte TPAF_UNIX_STREAM_BYTE = 0x31;
|
||||||
|
static final byte TPAF_UNIX_DGRAM_BYTE = 0x32;
|
||||||
|
|
||||||
|
private HAProxyConstants() { }
|
||||||
|
}
|
@ -17,44 +17,40 @@ package io.netty.handler.codec.haproxy;
|
|||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufProcessor;
|
import io.netty.buffer.ByteBufProcessor;
|
||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol.AddressFamily;
|
||||||
|
import io.netty.util.CharsetUtil;
|
||||||
import io.netty.util.NetUtil;
|
import io.netty.util.NetUtil;
|
||||||
|
import io.netty.util.internal.StringUtil;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message container for decoded HAProxy proxy protocol parameters
|
* Message container for decoded HAProxy proxy protocol parameters
|
||||||
*/
|
*/
|
||||||
public final class HAProxyProtocolMessage {
|
public final class HAProxyMessage {
|
||||||
/**
|
|
||||||
* The default system character encoding
|
|
||||||
*/
|
|
||||||
private static final Charset SYSTEM_CHARSET = Charset.defaultCharset();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version 1 proxy protocol message for 'UNKNOWN' proxied protocols. Per spec, when the proxied protocol is
|
* Version 1 proxy protocol message for 'UNKNOWN' proxied protocols. Per spec, when the proxied protocol is
|
||||||
* 'UNKNOWN' we must discard all other header values.
|
* 'UNKNOWN' we must discard all other header values.
|
||||||
*/
|
*/
|
||||||
private static final HAProxyProtocolMessage V1_UNKNOWN_MSG = new HAProxyProtocolMessage(HAProxyProtocolVersion.ONE,
|
private static final HAProxyMessage V1_UNKNOWN_MSG = new HAProxyMessage(
|
||||||
HAProxyProtocolCommand.PROXY, ProxiedProtocolAndFamily.UNKNOWN, null, null, 0, 0);
|
HAProxyProtocolVersion.V1, HAProxyCommand.PROXY, HAProxyProxiedProtocol.UNKNOWN, null, null, 0, 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version 2 proxy protocol message for 'UNKNOWN' proxied protocols. Per spec, when the proxied protocol is
|
* Version 2 proxy protocol message for 'UNKNOWN' proxied protocols. Per spec, when the proxied protocol is
|
||||||
* 'UNKNOWN' we must discard all other header values.
|
* 'UNKNOWN' we must discard all other header values.
|
||||||
*/
|
*/
|
||||||
private static final HAProxyProtocolMessage V2_UNKNOWN_MSG = new HAProxyProtocolMessage(HAProxyProtocolVersion.TWO,
|
private static final HAProxyMessage V2_UNKNOWN_MSG = new HAProxyMessage(
|
||||||
HAProxyProtocolCommand.PROXY, ProxiedProtocolAndFamily.UNKNOWN, null, null, 0, 0);
|
HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, HAProxyProxiedProtocol.UNKNOWN, null, null, 0, 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version 2 proxy protocol message for local requests. Per spec, we should use an unspecified protocol and family
|
* Version 2 proxy protocol message for local requests. Per spec, we should use an unspecified protocol and family
|
||||||
* for 'LOCAL' commands. Per spec, when the proxied protocol is 'UNKNOWN' we must discard all other header values.
|
* for 'LOCAL' commands. Per spec, when the proxied protocol is 'UNKNOWN' we must discard all other header values.
|
||||||
*/
|
*/
|
||||||
private static final HAProxyProtocolMessage V2_LOCAL_MSG = new HAProxyProtocolMessage(HAProxyProtocolVersion.TWO,
|
private static final HAProxyMessage V2_LOCAL_MSG = new HAProxyMessage(
|
||||||
HAProxyProtocolCommand.LOCAL, ProxiedProtocolAndFamily.UNKNOWN, null, null, 0, 0);
|
HAProxyProtocolVersion.V2, HAProxyCommand.LOCAL, HAProxyProxiedProtocol.UNKNOWN, null, null, 0, 0);
|
||||||
|
|
||||||
private final HAProxyProtocolVersion version;
|
private final HAProxyProtocolVersion protocolVersion;
|
||||||
private final HAProxyProtocolCommand command;
|
private final HAProxyCommand command;
|
||||||
private final ProxiedProtocolAndFamily paf;
|
private final HAProxyProxiedProtocol proxiedProtocol;
|
||||||
private final String sourceAddress;
|
private final String sourceAddress;
|
||||||
private final String destinationAddress;
|
private final String destinationAddress;
|
||||||
private final int sourcePort;
|
private final int sourcePort;
|
||||||
@ -63,82 +59,94 @@ public final class HAProxyProtocolMessage {
|
|||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*/
|
*/
|
||||||
private HAProxyProtocolMessage(HAProxyProtocolVersion ver, HAProxyProtocolCommand cmd, ProxiedProtocolAndFamily paf,
|
private HAProxyMessage(
|
||||||
String srcAddress, String dstAddress, String srcPort, String dstPort) {
|
HAProxyProtocolVersion protocolVersion, HAProxyCommand command, HAProxyProxiedProtocol proxiedProtocol,
|
||||||
this(ver, cmd, paf, srcAddress, dstAddress, portStringToInt(srcPort), portStringToInt(dstPort));
|
String sourceAddress, String destinationAddress, String sourcePort, String destinationPort) {
|
||||||
|
this(
|
||||||
|
protocolVersion, command, proxiedProtocol,
|
||||||
|
sourceAddress, destinationAddress, portStringToInt(sourcePort), portStringToInt(destinationPort));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*/
|
*/
|
||||||
private HAProxyProtocolMessage(HAProxyProtocolVersion ver, HAProxyProtocolCommand cmd, ProxiedProtocolAndFamily paf,
|
private HAProxyMessage(
|
||||||
String srcAddress, String dstAddress, int srcPort, int dstPort) {
|
HAProxyProtocolVersion protocolVersion, HAProxyCommand command, HAProxyProxiedProtocol proxiedProtocol,
|
||||||
|
String sourceAddress, String destinationAddress, int sourcePort, int destinationPort) {
|
||||||
|
|
||||||
ProxiedAddressFamily addrFamily;
|
AddressFamily addrFamily;
|
||||||
if (paf != null) {
|
if (proxiedProtocol != null) {
|
||||||
addrFamily = paf.proxiedAddressFamily();
|
addrFamily = proxiedProtocol.addressFamily();
|
||||||
} else {
|
} else {
|
||||||
addrFamily = null;
|
addrFamily = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAddress(srcAddress, addrFamily);
|
checkAddress(sourceAddress, addrFamily);
|
||||||
checkAddress(dstAddress, addrFamily);
|
checkAddress(destinationAddress, addrFamily);
|
||||||
checkPort(srcPort);
|
checkPort(sourcePort);
|
||||||
checkPort(dstPort);
|
checkPort(destinationPort);
|
||||||
|
|
||||||
this.version = ver;
|
this.protocolVersion = protocolVersion;
|
||||||
this.command = cmd;
|
this.command = command;
|
||||||
this.paf = paf;
|
this.proxiedProtocol = proxiedProtocol;
|
||||||
this.sourceAddress = srcAddress;
|
this.sourceAddress = sourceAddress;
|
||||||
this.destinationAddress = dstAddress;
|
this.destinationAddress = destinationAddress;
|
||||||
this.sourcePort = srcPort;
|
this.sourcePort = sourcePort;
|
||||||
this.destinationPort = dstPort;
|
this.destinationPort = destinationPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a version 2, binary proxy protocol header
|
* Decodes a version 2, binary proxy protocol header.
|
||||||
*
|
*
|
||||||
* @param header a version 2 proxy protocol header
|
* @param header a version 2 proxy protocol header
|
||||||
* @return {@link HAProxyProtocolMessage} instance
|
* @return {@link HAProxyMessage} instance
|
||||||
* @throws HAProxyProtocolException if any portion of the header is invalid
|
* @throws HAProxyProtocolException if any portion of the header is invalid
|
||||||
*/
|
*/
|
||||||
static HAProxyProtocolMessage decodeHeader(ByteBuf header) throws HAProxyProtocolException {
|
static HAProxyMessage decodeHeader(ByteBuf header) {
|
||||||
if (header == null) {
|
if (header == null) {
|
||||||
throw new HAProxyProtocolException("null header");
|
throw new NullPointerException("header");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.readableBytes() < 16) {
|
if (header.readableBytes() < 16) {
|
||||||
throw new HAProxyProtocolException("incomplete header (header must be at least 16 bytes)");
|
throw new HAProxyProtocolException(
|
||||||
|
"incomplete header: " + header.readableBytes() + " bytes (expected: 16+ bytes)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per spec, the 13th byte is the protocol version and command byte
|
// Per spec, the 13th byte is the protocol version and command byte
|
||||||
header.skipBytes(12);
|
header.skipBytes(12);
|
||||||
final byte verCmdByte = header.readByte();
|
final byte verCmdByte = header.readByte();
|
||||||
|
|
||||||
HAProxyProtocolVersion ver = HAProxyProtocolVersion.valueOf(verCmdByte);
|
HAProxyProtocolVersion ver;
|
||||||
|
try {
|
||||||
if (ver == null || !HAProxyProtocolVersion.TWO.equals(ver)) {
|
ver = HAProxyProtocolVersion.valueOf(verCmdByte);
|
||||||
throw new HAProxyProtocolException("unsupported header version 0x" + Integer.toHexString(verCmdByte));
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new HAProxyProtocolException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
HAProxyProtocolCommand cmd = HAProxyProtocolCommand.valueOf(verCmdByte);
|
if (ver != HAProxyProtocolVersion.V2) {
|
||||||
|
throw new HAProxyProtocolException("version 1 unsupported: 0x" + Integer.toHexString(verCmdByte));
|
||||||
if (cmd == null) {
|
|
||||||
throw new HAProxyProtocolException("unkown command 0x" + Integer.toHexString(verCmdByte));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HAProxyProtocolCommand.LOCAL.equals(cmd)) {
|
HAProxyCommand cmd;
|
||||||
|
try {
|
||||||
|
cmd = HAProxyCommand.valueOf(verCmdByte);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new HAProxyProtocolException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == HAProxyCommand.LOCAL) {
|
||||||
return V2_LOCAL_MSG;
|
return V2_LOCAL_MSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per spec, the 14th byte is the protocol and address family byte
|
// Per spec, the 14th byte is the protocol and address family byte
|
||||||
ProxiedProtocolAndFamily protAndFam = ProxiedProtocolAndFamily.valueOf(header.readByte());
|
HAProxyProxiedProtocol protAndFam;
|
||||||
|
try {
|
||||||
if (protAndFam == null) {
|
protAndFam = HAProxyProxiedProtocol.valueOf(header.readByte());
|
||||||
throw new HAProxyProtocolException("unkown protocol and family");
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new HAProxyProtocolException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProxiedProtocolAndFamily.UNKNOWN.equals(protAndFam)) {
|
if (protAndFam == HAProxyProxiedProtocol.UNKNOWN) {
|
||||||
return V2_UNKNOWN_MSG;
|
return V2_UNKNOWN_MSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,13 +158,14 @@ public final class HAProxyProtocolMessage {
|
|||||||
int srcPort = 0;
|
int srcPort = 0;
|
||||||
int dstPort = 0;
|
int dstPort = 0;
|
||||||
|
|
||||||
ProxiedAddressFamily addressFamily = protAndFam.proxiedAddressFamily();
|
AddressFamily addressFamily = protAndFam.addressFamily();
|
||||||
|
|
||||||
if (ProxiedAddressFamily.UNIX.equals(addressFamily)) {
|
if (addressFamily == AddressFamily.AF_UNIX) {
|
||||||
// unix sockets require 216 bytes for address information
|
// unix sockets require 216 bytes for address information
|
||||||
if (addressInfoLen < 216 || header.readableBytes() < 216) {
|
if (addressInfoLen < 216 || header.readableBytes() < 216) {
|
||||||
throw new HAProxyProtocolException(
|
throw new HAProxyProtocolException(
|
||||||
"incomplete address information (unix socket address info must be at least 216 bytes)");
|
"incomplete UNIX socket address information: " +
|
||||||
|
Math.min(addressInfoLen, header.readableBytes()) + " bytes (expected: 216+ bytes)");
|
||||||
}
|
}
|
||||||
int startIdx = header.readerIndex();
|
int startIdx = header.readerIndex();
|
||||||
int addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL);
|
int addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL);
|
||||||
@ -165,9 +174,9 @@ public final class HAProxyProtocolMessage {
|
|||||||
} else {
|
} else {
|
||||||
addressLen = addressEnd - startIdx;
|
addressLen = addressEnd - startIdx;
|
||||||
}
|
}
|
||||||
srcAddress = header.toString(startIdx, addressLen, SYSTEM_CHARSET);
|
srcAddress = header.toString(startIdx, addressLen, CharsetUtil.US_ASCII);
|
||||||
|
|
||||||
startIdx = startIdx + 108;
|
startIdx += 108;
|
||||||
|
|
||||||
addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL);
|
addressEnd = header.forEachByte(startIdx, 108, ByteBufProcessor.FIND_NUL);
|
||||||
if (addressEnd == -1) {
|
if (addressEnd == -1) {
|
||||||
@ -175,25 +184,27 @@ public final class HAProxyProtocolMessage {
|
|||||||
} else {
|
} else {
|
||||||
addressLen = addressEnd - startIdx;
|
addressLen = addressEnd - startIdx;
|
||||||
}
|
}
|
||||||
dstAddress = header.toString(startIdx, addressLen, SYSTEM_CHARSET);
|
dstAddress = header.toString(startIdx, addressLen, CharsetUtil.US_ASCII);
|
||||||
} else {
|
} else {
|
||||||
if (ProxiedAddressFamily.IPV4.equals(addressFamily)) {
|
if (addressFamily == AddressFamily.AF_IPv4) {
|
||||||
// IPv4 requires 12 bytes for address information
|
// IPv4 requires 12 bytes for address information
|
||||||
if (addressInfoLen < 12 || header.readableBytes() < 12) {
|
if (addressInfoLen < 12 || header.readableBytes() < 12) {
|
||||||
throw new HAProxyProtocolException(
|
throw new HAProxyProtocolException(
|
||||||
"incomplete address information (IPv4 address info must be at least 12 bytes)");
|
"incomplete IPv4 address information: " +
|
||||||
|
Math.min(addressInfoLen, header.readableBytes()) + " bytes (expected: 12+ bytes)");
|
||||||
}
|
}
|
||||||
addressLen = 4;
|
addressLen = 4;
|
||||||
} else if (ProxiedAddressFamily.IPV6.equals(addressFamily)) {
|
} else if (addressFamily == AddressFamily.AF_IPv6) {
|
||||||
// IPv6 requires 36 bytes for address information
|
// IPv6 requires 36 bytes for address information
|
||||||
if (addressInfoLen < 36 || header.readableBytes() < 36) {
|
if (addressInfoLen < 36 || header.readableBytes() < 36) {
|
||||||
throw new HAProxyProtocolException(
|
throw new HAProxyProtocolException(
|
||||||
"incomplete address information (IPv6 address info must be at least 36 bytes)");
|
"incomplete IPv6 address information: " +
|
||||||
|
Math.min(addressInfoLen, header.readableBytes()) + " bytes (expected: 36+ bytes)");
|
||||||
}
|
}
|
||||||
addressLen = 16;
|
addressLen = 16;
|
||||||
} else {
|
} else {
|
||||||
throw new HAProxyProtocolException(
|
throw new HAProxyProtocolException(
|
||||||
"unable to parse address information (unkown address family " + addressFamily + ")");
|
"unable to parse address information (unkown address family: " + addressFamily + ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per spec, the src address begins at the 17th byte
|
// Per spec, the src address begins at the 17th byte
|
||||||
@ -203,19 +214,19 @@ public final class HAProxyProtocolMessage {
|
|||||||
dstPort = header.readUnsignedShort();
|
dstPort = header.readUnsignedShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new HAProxyProtocolMessage(ver, cmd, protAndFam, srcAddress, dstAddress, srcPort, dstPort);
|
return new HAProxyMessage(ver, cmd, protAndFam, srcAddress, dstAddress, srcPort, dstPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a version 1, human-readable proxy protocol header
|
* Decodes a version 1, human-readable proxy protocol header.
|
||||||
*
|
*
|
||||||
* @param header a version 1 proxy protocol header
|
* @param header a version 1 proxy protocol header
|
||||||
* @return {@link HAProxyProtocolMessage} instance
|
* @return {@link HAProxyMessage} instance
|
||||||
* @throws HAProxyProtocolException if any portion of the header is invalid
|
* @throws HAProxyProtocolException if any portion of the header is invalid
|
||||||
*/
|
*/
|
||||||
static HAProxyProtocolMessage decodeHeader(String header) throws HAProxyProtocolException {
|
static HAProxyMessage decodeHeader(String header) {
|
||||||
if (header == null) {
|
if (header == null) {
|
||||||
throw new HAProxyProtocolException("null header");
|
throw new HAProxyProtocolException("header");
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] parts = StringUtil.split(header, ' ');
|
String[] parts = StringUtil.split(header, ' ');
|
||||||
@ -223,32 +234,36 @@ public final class HAProxyProtocolMessage {
|
|||||||
|
|
||||||
if (numParts < 2) {
|
if (numParts < 2) {
|
||||||
throw new HAProxyProtocolException(
|
throw new HAProxyProtocolException(
|
||||||
"invalid format (header must at least contain protocol and proxied protocol values)");
|
"invalid header: " + header + " (expected: 'PROXY' and proxied protocol values)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!"PROXY".equals(parts[0])) {
|
if (!"PROXY".equals(parts[0])) {
|
||||||
throw new HAProxyProtocolException("unsupported protocol " + parts[0]);
|
throw new HAProxyProtocolException("unknown identifier: " + parts[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxiedProtocolAndFamily protAndFam = ProxiedProtocolAndFamily.valueOf(parts[1]);
|
HAProxyProxiedProtocol protAndFam;
|
||||||
|
try {
|
||||||
boolean validPaf = protAndFam != null &&
|
protAndFam = HAProxyProxiedProtocol.valueOf(parts[1]);
|
||||||
(ProxiedProtocolAndFamily.TCP4.equals(protAndFam) || ProxiedProtocolAndFamily.TCP6.equals(protAndFam) ||
|
} catch (IllegalArgumentException e) {
|
||||||
ProxiedProtocolAndFamily.UNKNOWN.equals(protAndFam));
|
throw new HAProxyProtocolException(e);
|
||||||
|
|
||||||
if (!validPaf) {
|
|
||||||
throw new HAProxyProtocolException("unsupported v1 proxied protocol " + parts[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProxiedProtocolAndFamily.UNKNOWN.equals(protAndFam)) {
|
if (protAndFam != HAProxyProxiedProtocol.TCP4 &&
|
||||||
|
protAndFam != HAProxyProxiedProtocol.TCP6 &&
|
||||||
|
protAndFam != HAProxyProxiedProtocol.UNKNOWN) {
|
||||||
|
throw new HAProxyProtocolException("unsupported v1 proxied protocol: " + parts[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protAndFam == HAProxyProxiedProtocol.UNKNOWN) {
|
||||||
return V1_UNKNOWN_MSG;
|
return V1_UNKNOWN_MSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numParts != 6) {
|
if (numParts != 6) {
|
||||||
throw new HAProxyProtocolException("invalid format (header must contain exactly 6 values for TCP proxies)");
|
throw new HAProxyProtocolException("invalid TCP4/6 header: " + header + " (expected: 6 parts)");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new HAProxyProtocolMessage(HAProxyProtocolVersion.ONE, HAProxyProtocolCommand.PROXY,
|
return new HAProxyMessage(
|
||||||
|
HAProxyProtocolVersion.V1, HAProxyCommand.PROXY,
|
||||||
protAndFam, parts[2], parts[3], parts[4], parts[5]);
|
protAndFam, parts[2], parts[3], parts[4], parts[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,27 +278,27 @@ public final class HAProxyProtocolMessage {
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (addressLen == 4) {
|
if (addressLen == 4) {
|
||||||
sb.append(header.readByte() & 0xff);
|
sb.append(header.readByte() & 0xff);
|
||||||
sb.append(".");
|
sb.append('.');
|
||||||
sb.append(header.readByte() & 0xff);
|
sb.append(header.readByte() & 0xff);
|
||||||
sb.append(".");
|
sb.append('.');
|
||||||
sb.append(header.readByte() & 0xff);
|
sb.append(header.readByte() & 0xff);
|
||||||
sb.append(".");
|
sb.append('.');
|
||||||
sb.append(header.readByte() & 0xff);
|
sb.append(header.readByte() & 0xff);
|
||||||
} else {
|
} else {
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
sb.append(":");
|
sb.append(':');
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
sb.append(":");
|
sb.append(':');
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
sb.append(":");
|
sb.append(':');
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
sb.append(":");
|
sb.append(':');
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
sb.append(":");
|
sb.append(':');
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
sb.append(":");
|
sb.append(':');
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
sb.append(":");
|
sb.append(':');
|
||||||
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
sb.append(Integer.toHexString(header.readUnsignedShort()));
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@ -292,49 +307,59 @@ public final class HAProxyProtocolMessage {
|
|||||||
/**
|
/**
|
||||||
* Convert port to integer
|
* Convert port to integer
|
||||||
*
|
*
|
||||||
* @param port the port
|
* @param value the port
|
||||||
* @return port as integer
|
* @return port as an integer
|
||||||
* @throws HAProxyProtocolException if port is not a valid integer
|
* @throws HAProxyProtocolException if port is not a valid integer
|
||||||
*/
|
*/
|
||||||
private static int portStringToInt(String port) throws HAProxyProtocolException {
|
private static int portStringToInt(String value) {
|
||||||
|
int port;
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(port);
|
port = Integer.parseInt(value);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new HAProxyProtocolException(port + " is not a valid port", e);
|
throw new HAProxyProtocolException("invalid port: " + value, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (port <= 0 || port > 65535) {
|
||||||
|
throw new HAProxyProtocolException("invalid port: " + value + " (expected: 1 ~ 65535)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate an address (IPv4, IPv6, Unix Socket)
|
* Validate an address (IPv4, IPv6, Unix Socket)
|
||||||
*
|
*
|
||||||
* @param address human-readable address
|
* @param address human-readable address
|
||||||
* @param addrFamily the {@link ProxiedAddressFamily} to check the address against
|
* @param addrFamily the {@link AddressFamily} to check the address against
|
||||||
* @throws HAProxyProtocolException if the address is invalid
|
* @throws HAProxyProtocolException if the address is invalid
|
||||||
*/
|
*/
|
||||||
private static void checkAddress(String address, ProxiedAddressFamily addrFamily) throws HAProxyProtocolException {
|
private static void checkAddress(String address, AddressFamily addrFamily) {
|
||||||
|
if (address == null) {
|
||||||
|
throw new NullPointerException("address");
|
||||||
|
}
|
||||||
|
|
||||||
if (addrFamily == null) {
|
if (addrFamily == null) {
|
||||||
throw new HAProxyProtocolException("unable to validate address because no address family is set");
|
throw new NullPointerException("addrFamily");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProxiedAddressFamily.UNSPECIFIED.equals(addrFamily) && address != null) {
|
if (addrFamily == AddressFamily.AF_UNSPEC) {
|
||||||
throw new HAProxyProtocolException(
|
throw new HAProxyProtocolException("unable to validate an AF_UNSPEC address: " + address);
|
||||||
"unable to validate address because address family is " + addrFamily);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProxiedAddressFamily.UNIX.equals(addrFamily)) {
|
if (addrFamily == AddressFamily.AF_UNIX) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isValid = true;
|
boolean isValid = true;
|
||||||
|
|
||||||
if (ProxiedAddressFamily.IPV4.equals(addrFamily)) {
|
if (addrFamily == AddressFamily.AF_IPv4) {
|
||||||
isValid = NetUtil.isValidIpV4Address(address);
|
isValid = NetUtil.isValidIpV4Address(address);
|
||||||
} else if (ProxiedAddressFamily.IPV6.equals(addrFamily)) {
|
} else if (addrFamily == AddressFamily.AF_IPv6) {
|
||||||
isValid = NetUtil.isValidIpV6Address(address);
|
isValid = NetUtil.isValidIpV6Address(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
throw new HAProxyProtocolException(address + " is not a valid " + addrFamily + " address");
|
throw new HAProxyProtocolException("invalid " + addrFamily + " address: " + address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,70 +369,56 @@ public final class HAProxyProtocolMessage {
|
|||||||
* @param port the UDP/TCP port
|
* @param port the UDP/TCP port
|
||||||
* @throws HAProxyProtocolException if the port is out of range (0-65535 inclusive)
|
* @throws HAProxyProtocolException if the port is out of range (0-65535 inclusive)
|
||||||
*/
|
*/
|
||||||
private static void checkPort(int port) throws HAProxyProtocolException {
|
private static void checkPort(int port) {
|
||||||
if (port < 0 || port > 65535) {
|
if (port < 0 || port > 65535) {
|
||||||
throw new HAProxyProtocolException(port + " is not a valid port");
|
throw new HAProxyProtocolException("invalid port: " + port + " (expected: 1 ~ 65535)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link HAProxyProtocolVersion} of this {@link HAProxyProtocolMessage}
|
* Returns the {@link HAProxyProtocolVersion} of this {@link HAProxyMessage}.
|
||||||
*
|
|
||||||
* @return the proxy protocol specification version
|
|
||||||
*/
|
*/
|
||||||
public HAProxyProtocolVersion version() {
|
public HAProxyProtocolVersion protocolVersion() {
|
||||||
return version;
|
return protocolVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link HAProxyProtocolCommand} of this {@link HAProxyProtocolMessage}
|
* Returns the {@link HAProxyCommand} of this {@link HAProxyMessage}.
|
||||||
*
|
|
||||||
* @return the proxy protocol command
|
|
||||||
*/
|
*/
|
||||||
public HAProxyProtocolCommand command() {
|
public HAProxyCommand command() {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link ProxiedProtocolAndFamily} of this {@link HAProxyProtocolMessage}
|
* Returns the {@link HAProxyProxiedProtocol} of this {@link HAProxyMessage}.
|
||||||
*
|
|
||||||
* @return the proxied protocol and address family
|
|
||||||
*/
|
*/
|
||||||
public ProxiedProtocolAndFamily protocolAndFamily() {
|
public HAProxyProxiedProtocol proxiedProtocol() {
|
||||||
return paf;
|
return proxiedProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the human-readable source address of this {@link HAProxyProtocolMessage}
|
* Returns the human-readable source address of this {@link HAProxyMessage}.
|
||||||
*
|
|
||||||
* @return the human-readable source address
|
|
||||||
*/
|
*/
|
||||||
public String sourceAddress() {
|
public String sourceAddress() {
|
||||||
return sourceAddress;
|
return sourceAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the human-readable destination address of this {@link HAProxyProtocolMessage}
|
* Returns the human-readable destination address of this {@link HAProxyMessage}.
|
||||||
*
|
|
||||||
* @return the human-readable destination address
|
|
||||||
*/
|
*/
|
||||||
public String destinationAddress() {
|
public String destinationAddress() {
|
||||||
return destinationAddress;
|
return destinationAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the UDP/TCP source port of this {@link HAProxyProtocolMessage}
|
* Returns the UDP/TCP source port of this {@link HAProxyMessage}.
|
||||||
*
|
|
||||||
* @return the UDP/TCP source port
|
|
||||||
*/
|
*/
|
||||||
public int sourcePort() {
|
public int sourcePort() {
|
||||||
return sourcePort;
|
return sourcePort;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the UDP/TCP destination port of this {@link HAProxyProtocolMessage}
|
* Returns the UDP/TCP destination port of this {@link HAProxyMessage}.
|
||||||
*
|
|
||||||
* @return the UDP/TCP destination port
|
|
||||||
*/
|
*/
|
||||||
public int destinationPort() {
|
public int destinationPort() {
|
||||||
return destinationPort;
|
return destinationPort;
|
@ -18,6 +18,7 @@ package io.netty.handler.codec.haproxy;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
|
import io.netty.handler.codec.LineBasedFrameDecoder;
|
||||||
import io.netty.util.CharsetUtil;
|
import io.netty.util.CharsetUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -27,7 +28,7 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @see <a href="http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt">Proxy Protocol Specification</a>
|
* @see <a href="http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt">Proxy Protocol Specification</a>
|
||||||
*/
|
*/
|
||||||
public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
public class HAProxyMessageDecoder extends ByteToMessageDecoder {
|
||||||
/**
|
/**
|
||||||
* Maximum possible length of a v1 proxy protocol header per spec
|
* Maximum possible length of a v1 proxy protocol header per spec
|
||||||
*/
|
*/
|
||||||
@ -56,7 +57,7 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
/**
|
/**
|
||||||
* Binary header prefix
|
* Binary header prefix
|
||||||
*/
|
*/
|
||||||
private static final byte[] BINARY_PREFIX = new byte[] {
|
private static final byte[] BINARY_PREFIX = {
|
||||||
(byte) 0x0D,
|
(byte) 0x0D,
|
||||||
(byte) 0x0A,
|
(byte) 0x0A,
|
||||||
(byte) 0x0D,
|
(byte) 0x0D,
|
||||||
@ -100,13 +101,13 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
* The latest v2 spec (2014/05/18) allows for additional data to be sent in the proxy protocol header beyond the
|
* The latest v2 spec (2014/05/18) allows for additional data to be sent in the proxy protocol header beyond the
|
||||||
* address information block so now we need a configurable max header size
|
* address information block so now we need a configurable max header size
|
||||||
*/
|
*/
|
||||||
private int v2MaxHeaderSize;
|
private final int v2MaxHeaderSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new decoder with no additional data (TLV) restrictions
|
* Creates a new decoder with no additional data (TLV) restrictions
|
||||||
*/
|
*/
|
||||||
public HAProxyProtocolDecoder() {
|
public HAProxyMessageDecoder() {
|
||||||
this.v2MaxHeaderSize = V2_MAX_LENGTH;
|
v2MaxHeaderSize = V2_MAX_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,17 +120,17 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
*
|
*
|
||||||
* @param maxTlvSize maximum number of bytes allowed for additional data (Type-Length-Value vectors) in a v2 header
|
* @param maxTlvSize maximum number of bytes allowed for additional data (Type-Length-Value vectors) in a v2 header
|
||||||
*/
|
*/
|
||||||
public HAProxyProtocolDecoder(int maxTlvSize) {
|
public HAProxyMessageDecoder(int maxTlvSize) {
|
||||||
if (maxTlvSize < 1) {
|
if (maxTlvSize < 1) {
|
||||||
this.v2MaxHeaderSize = V2_MIN_LENGTH;
|
v2MaxHeaderSize = V2_MIN_LENGTH;
|
||||||
} else if (maxTlvSize > V2_MAX_TLV) {
|
} else if (maxTlvSize > V2_MAX_TLV) {
|
||||||
this.v2MaxHeaderSize = V2_MAX_LENGTH;
|
v2MaxHeaderSize = V2_MAX_LENGTH;
|
||||||
} else {
|
} else {
|
||||||
int calcMax = maxTlvSize + V2_MIN_LENGTH;
|
int calcMax = maxTlvSize + V2_MIN_LENGTH;
|
||||||
if (calcMax > V2_MAX_LENGTH) {
|
if (calcMax > V2_MAX_LENGTH) {
|
||||||
this.v2MaxHeaderSize = V2_MAX_LENGTH;
|
v2MaxHeaderSize = V2_MAX_LENGTH;
|
||||||
} else {
|
} else {
|
||||||
this.v2MaxHeaderSize = calcMax;
|
v2MaxHeaderSize = calcMax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,9 +234,9 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
finished = true;
|
finished = true;
|
||||||
try {
|
try {
|
||||||
if (version == 1) {
|
if (version == 1) {
|
||||||
out.add(HAProxyProtocolMessage.decodeHeader(decoded.toString(CharsetUtil.US_ASCII)));
|
out.add(HAProxyMessage.decodeHeader(decoded.toString(CharsetUtil.US_ASCII)));
|
||||||
} else {
|
} else {
|
||||||
out.add(HAProxyProtocolMessage.decodeHeader(decoded));
|
out.add(HAProxyMessage.decodeHeader(decoded));
|
||||||
}
|
}
|
||||||
} catch (HAProxyProtocolException e) {
|
} catch (HAProxyProtocolException e) {
|
||||||
fail(ctx, null, e);
|
fail(ctx, null, e);
|
||||||
@ -247,7 +248,7 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
* Create a frame out of the {@link ByteBuf} and return it.
|
* Create a frame out of the {@link ByteBuf} and return it.
|
||||||
* Based on code from {@link LineBasedFrameDecoder#decode(ChannelHandlerContext, ByteBuf)}.
|
* Based on code from {@link LineBasedFrameDecoder#decode(ChannelHandlerContext, ByteBuf)}.
|
||||||
*
|
*
|
||||||
* @param ctx the {@link ChannelHandlerContext} which this {@link HAProxyProtocolDecoder} belongs to
|
* @param ctx the {@link ChannelHandlerContext} which this {@link HAProxyMessageDecoder} belongs to
|
||||||
* @param buffer the {@link ByteBuf} from which to read data
|
* @param buffer the {@link ByteBuf} from which to read data
|
||||||
* @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could
|
* @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could
|
||||||
* be created
|
* be created
|
||||||
@ -275,7 +276,6 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (eoh >= 0) {
|
if (eoh >= 0) {
|
||||||
final int length = discardedBytes + eoh - buffer.readerIndex();
|
|
||||||
buffer.readerIndex(eoh);
|
buffer.readerIndex(eoh);
|
||||||
discardedBytes = 0;
|
discardedBytes = 0;
|
||||||
discarding = false;
|
discarding = false;
|
||||||
@ -291,7 +291,7 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
* Create a frame out of the {@link ByteBuf} and return it.
|
* Create a frame out of the {@link ByteBuf} and return it.
|
||||||
* Based on code from {@link LineBasedFrameDecoder#decode(ChannelHandlerContext, ByteBuf)}.
|
* Based on code from {@link LineBasedFrameDecoder#decode(ChannelHandlerContext, ByteBuf)}.
|
||||||
*
|
*
|
||||||
* @param ctx the {@link ChannelHandlerContext} which this {@link HAProxyProtocolDecoder} belongs to
|
* @param ctx the {@link ChannelHandlerContext} which this {@link HAProxyMessageDecoder} belongs to
|
||||||
* @param buffer the {@link ByteBuf} from which to read data
|
* @param buffer the {@link ByteBuf} from which to read data
|
||||||
* @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could
|
* @return frame the {@link ByteBuf} which represent the frame or {@code null} if no frame could
|
||||||
* be created
|
* be created
|
||||||
@ -321,7 +321,6 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (eol >= 0) {
|
if (eol >= 0) {
|
||||||
final int length = discardedBytes + eol - buffer.readerIndex();
|
|
||||||
final int delimLength = buffer.getByte(eol) == '\r' ? 2 : 1;
|
final int delimLength = buffer.getByte(eol) == '\r' ? 2 : 1;
|
||||||
buffer.readerIndex(eol + delimLength);
|
buffer.readerIndex(eol + delimLength);
|
||||||
discardedBytes = 0;
|
discardedBytes = 0;
|
||||||
@ -340,7 +339,7 @@ public class HAProxyProtocolDecoder extends ByteToMessageDecoder {
|
|||||||
|
|
||||||
private void failOverLimit(final ChannelHandlerContext ctx, String length) {
|
private void failOverLimit(final ChannelHandlerContext ctx, String length) {
|
||||||
int maxLength = version == 1 ? V1_MAX_LENGTH : v2MaxHeaderSize;
|
int maxLength = version == 1 ? V1_MAX_LENGTH : v2MaxHeaderSize;
|
||||||
fail(ctx, "header length (" + length + ") exceeds the allowed maximum (" + maxLength + ")", null);
|
fail(ctx, "header length (" + length + ") exceeds the allowed maximum (" + maxLength + ')', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fail(final ChannelHandlerContext ctx, String errMsg, Throwable t) {
|
private void fail(final ChannelHandlerContext ctx, String errMsg, Throwable t) {
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The command of an HAProxy proxy protocol header
|
|
||||||
*/
|
|
||||||
public final class HAProxyProtocolCommand implements Comparable<HAProxyProtocolCommand> {
|
|
||||||
/**
|
|
||||||
* The command is specified in the lowest 4 bits of the protocol version and command byte
|
|
||||||
*/
|
|
||||||
private static final byte COMMAND_MASK = (byte) 0x0f;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Version byte constants
|
|
||||||
*/
|
|
||||||
private static final byte LOCAL_BYTE = (byte) 0x00;
|
|
||||||
private static final byte PROXY_BYTE = (byte) 0x01;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The LOCAL command represents a connection that was established on purpose by the proxy
|
|
||||||
* without being relayed
|
|
||||||
*/
|
|
||||||
public static final HAProxyProtocolCommand LOCAL = new HAProxyProtocolCommand("LOCAL", LOCAL_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The PROXY command represents a connection that was established on behalf of another node,
|
|
||||||
* and reflects the original connection endpoints
|
|
||||||
*/
|
|
||||||
public static final HAProxyProtocolCommand PROXY = new HAProxyProtocolCommand("PROXY", PROXY_BYTE);
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final byte cmdByte;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance
|
|
||||||
*/
|
|
||||||
private HAProxyProtocolCommand(String name, byte cmdByte) {
|
|
||||||
this.name = name;
|
|
||||||
this.cmdByte = cmdByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link HAProxyProtocolCommand} represented by the specified protocol version and command byte
|
|
||||||
*
|
|
||||||
* @param verCmdByte protocol version and command byte
|
|
||||||
* @return {@link HAProxyProtocolCommand} instance OR {@code null} if the command is not recognized
|
|
||||||
*/
|
|
||||||
public static HAProxyProtocolCommand valueOf(byte verCmdByte) {
|
|
||||||
switch ((byte) (verCmdByte & COMMAND_MASK)) {
|
|
||||||
case PROXY_BYTE:
|
|
||||||
return PROXY;
|
|
||||||
case LOCAL_BYTE:
|
|
||||||
return LOCAL;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this command
|
|
||||||
*
|
|
||||||
* @return the name of this command
|
|
||||||
*/
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte value of this command
|
|
||||||
*
|
|
||||||
* @return the byte value of this command
|
|
||||||
*/
|
|
||||||
public byte byteValue() {
|
|
||||||
return cmdByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof HAProxyProtocolCommand)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HAProxyProtocolCommand that = (HAProxyProtocolCommand) o;
|
|
||||||
return byteValue() == that.byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(HAProxyProtocolCommand o) {
|
|
||||||
return byteValue() - o.byteValue();
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,8 +27,7 @@ public class HAProxyProtocolException extends DecoderException {
|
|||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*/
|
*/
|
||||||
public HAProxyProtocolException() {
|
public HAProxyProtocolException() { }
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
|
@ -15,100 +15,56 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.haproxy;
|
package io.netty.handler.codec.haproxy;
|
||||||
|
|
||||||
|
import static io.netty.handler.codec.haproxy.HAProxyConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The HAProxy proxy protocol specification version
|
* The HAProxy proxy protocol specification version.
|
||||||
*/
|
*/
|
||||||
public final class HAProxyProtocolVersion implements Comparable<HAProxyProtocolVersion> {
|
public enum HAProxyProtocolVersion {
|
||||||
|
/**
|
||||||
|
* The ONE proxy protocol version represents a version 1 (human-readable) header.
|
||||||
|
*/
|
||||||
|
V1(VERSION_ONE_BYTE),
|
||||||
|
/**
|
||||||
|
* The TWO proxy protocol version represents a version 2 (binary) header.
|
||||||
|
*/
|
||||||
|
V2(VERSION_TWO_BYTE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The highest 4 bits of the protocol version and command byte contain the version
|
* The highest 4 bits of the protocol version and command byte contain the version
|
||||||
*/
|
*/
|
||||||
private static final byte VERSION_MASK = (byte) 0xf0;
|
private static final byte VERSION_MASK = (byte) 0xf0;
|
||||||
|
|
||||||
/**
|
private final byte byteValue;
|
||||||
* Version byte constants
|
|
||||||
*/
|
|
||||||
private static final byte ONE_BYTE = (byte) 0x10;
|
|
||||||
private static final byte TWO_BYTE = (byte) 0x20;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ONE proxy protocol version represents a version 1 (human-readable) header
|
|
||||||
*/
|
|
||||||
public static final HAProxyProtocolVersion ONE = new HAProxyProtocolVersion("ONE", ONE_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The TWO proxy protocol version represents a version 2 (binary) header
|
|
||||||
*/
|
|
||||||
public static final HAProxyProtocolVersion TWO = new HAProxyProtocolVersion("TWO", TWO_BYTE);
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final byte versionByte;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
*/
|
*/
|
||||||
private HAProxyProtocolVersion(String name, byte versionByte) {
|
HAProxyProtocolVersion(byte byteValue) {
|
||||||
this.name = name;
|
this.byteValue = byteValue;
|
||||||
this.versionByte = versionByte;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link HAProxyProtocolVersion} represented by the specified protocol version and command byte
|
* Returns the {@link HAProxyProtocolVersion} represented by the higest 4 bits of the specified byte.
|
||||||
*
|
*
|
||||||
* @param verCmdByte protocol version and command byte
|
* @param verCmdByte protocol version and command byte
|
||||||
* @return {@link HAProxyProtocolVersion} instance OR {@code null} if the
|
|
||||||
* version is not recognized
|
|
||||||
*/
|
*/
|
||||||
public static HAProxyProtocolVersion valueOf(byte verCmdByte) {
|
public static HAProxyProtocolVersion valueOf(byte verCmdByte) {
|
||||||
switch ((byte) (verCmdByte & VERSION_MASK)) {
|
int version = verCmdByte & VERSION_MASK;
|
||||||
case TWO_BYTE:
|
switch ((byte) version) {
|
||||||
return TWO;
|
case VERSION_TWO_BYTE:
|
||||||
case ONE_BYTE:
|
return V2;
|
||||||
return ONE;
|
case VERSION_ONE_BYTE:
|
||||||
|
return V1;
|
||||||
default:
|
default:
|
||||||
return null;
|
throw new IllegalArgumentException("unknown version: " + version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of this version
|
* Returns the byte value of this version.
|
||||||
*
|
|
||||||
* @return the name of this version
|
|
||||||
*/
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte value of this version
|
|
||||||
*
|
|
||||||
* @return the byte value of this version
|
|
||||||
*/
|
*/
|
||||||
public byte byteValue() {
|
public byte byteValue() {
|
||||||
return versionByte;
|
return byteValue;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof HAProxyProtocolVersion)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HAProxyProtocolVersion that = (HAProxyProtocolVersion) o;
|
|
||||||
return byteValue() == that.byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(HAProxyProtocolVersion o) {
|
|
||||||
return byteValue() - o.byteValue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
||||||
|
|
||||||
|
import static io.netty.handler.codec.haproxy.HAProxyConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A protocol proxied by HAProxy which is represented by its transport protocol and address family.
|
||||||
|
*/
|
||||||
|
public enum HAProxyProxiedProtocol {
|
||||||
|
/**
|
||||||
|
* The UNKNOWN represents a connection which was forwarded for an unknown protocol and an unknown address family.
|
||||||
|
*/
|
||||||
|
UNKNOWN(TPAF_UNKNOWN_BYTE, AddressFamily.AF_UNSPEC, TransportProtocol.UNSPEC),
|
||||||
|
/**
|
||||||
|
* The TCP4 represents a connection which was forwarded for an IPv4 client over TCP.
|
||||||
|
*/
|
||||||
|
TCP4(TPAF_TCP4_BYTE, AddressFamily.AF_IPv4, TransportProtocol.STREAM),
|
||||||
|
/**
|
||||||
|
* The TCP6 represents a connection which was forwarded for an IPv6 client over TCP.
|
||||||
|
*/
|
||||||
|
TCP6(TPAF_TCP6_BYTE, AddressFamily.AF_IPv6, TransportProtocol.STREAM),
|
||||||
|
/**
|
||||||
|
* The UDP4 represents a connection which was forwarded for an IPv4 client over UDP.
|
||||||
|
*/
|
||||||
|
UDP4(TPAF_UDP4_BYTE, AddressFamily.AF_IPv4, TransportProtocol.DGRAM),
|
||||||
|
/**
|
||||||
|
* The UDP6 represents a connection which was forwarded for an IPv6 client over UDP.
|
||||||
|
*/
|
||||||
|
UDP6(TPAF_UDP6_BYTE, AddressFamily.AF_IPv6, TransportProtocol.DGRAM),
|
||||||
|
/**
|
||||||
|
* The UNIX_STREAM represents a connection which was forwarded for a UNIX stream socket.
|
||||||
|
*/
|
||||||
|
UNIX_STREAM(TPAF_UNIX_STREAM_BYTE, AddressFamily.AF_UNIX, TransportProtocol.STREAM),
|
||||||
|
/**
|
||||||
|
* The UNIX_DGRAM represents a connection which was forwarded for a UNIX datagram socket.
|
||||||
|
*/
|
||||||
|
UNIX_DGRAM(TPAF_UNIX_DGRAM_BYTE, AddressFamily.AF_UNIX, TransportProtocol.DGRAM);
|
||||||
|
|
||||||
|
private final byte byteValue;
|
||||||
|
private final AddressFamily addressFamily;
|
||||||
|
private final TransportProtocol transportProtocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance.
|
||||||
|
*/
|
||||||
|
HAProxyProxiedProtocol(
|
||||||
|
byte byteValue,
|
||||||
|
AddressFamily addressFamily,
|
||||||
|
TransportProtocol transportProtocol) {
|
||||||
|
|
||||||
|
this.byteValue = byteValue;
|
||||||
|
this.addressFamily = addressFamily;
|
||||||
|
this.transportProtocol = transportProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link HAProxyProxiedProtocol} represented by the specified byte.
|
||||||
|
*
|
||||||
|
* @param tpafByte transport protocol and address family byte
|
||||||
|
*/
|
||||||
|
public static HAProxyProxiedProtocol valueOf(byte tpafByte) {
|
||||||
|
switch (tpafByte) {
|
||||||
|
case TPAF_TCP4_BYTE:
|
||||||
|
return TCP4;
|
||||||
|
case TPAF_TCP6_BYTE:
|
||||||
|
return TCP6;
|
||||||
|
case TPAF_UNKNOWN_BYTE:
|
||||||
|
return UNKNOWN;
|
||||||
|
case TPAF_UDP4_BYTE:
|
||||||
|
return UDP4;
|
||||||
|
case TPAF_UDP6_BYTE:
|
||||||
|
return UDP6;
|
||||||
|
case TPAF_UNIX_STREAM_BYTE:
|
||||||
|
return UNIX_STREAM;
|
||||||
|
case TPAF_UNIX_DGRAM_BYTE:
|
||||||
|
return UNIX_DGRAM;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"unknown transport protocol + address family: " + (tpafByte & 0xFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the byte value of this protocol and address family.
|
||||||
|
*/
|
||||||
|
public byte byteValue() {
|
||||||
|
return byteValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link AddressFamily} of this protocol and address family.
|
||||||
|
*/
|
||||||
|
public AddressFamily addressFamily() {
|
||||||
|
return addressFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link TransportProtocol} of this protocol and address family.
|
||||||
|
*/
|
||||||
|
public TransportProtocol transportProtocol() {
|
||||||
|
return transportProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address family of an HAProxy proxy protocol header.
|
||||||
|
*/
|
||||||
|
public enum AddressFamily {
|
||||||
|
/**
|
||||||
|
* The UNSPECIFIED address family represents a connection which was forwarded for an unkown protocol.
|
||||||
|
*/
|
||||||
|
AF_UNSPEC(AF_UNSPEC_BYTE),
|
||||||
|
/**
|
||||||
|
* The IPV4 address family represents a connection which was forwarded for an IPV4 client.
|
||||||
|
*/
|
||||||
|
AF_IPv4(AF_IPV4_BYTE),
|
||||||
|
/**
|
||||||
|
* The IPV6 address family represents a connection which was forwarded for an IPV6 client.
|
||||||
|
*/
|
||||||
|
AF_IPv6(AF_IPV6_BYTE),
|
||||||
|
/**
|
||||||
|
* The UNIX address family represents a connection which was forwarded for a unix socket.
|
||||||
|
*/
|
||||||
|
AF_UNIX(AF_UNIX_BYTE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The highest 4 bits of the transport protocol and address family byte contain the address family
|
||||||
|
*/
|
||||||
|
private static final byte FAMILY_MASK = (byte) 0xf0;
|
||||||
|
|
||||||
|
private final byte byteValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance
|
||||||
|
*/
|
||||||
|
AddressFamily(byte byteValue) {
|
||||||
|
this.byteValue = byteValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link AddressFamily} represented by the highest 4 bits of the specified byte.
|
||||||
|
*
|
||||||
|
* @param tpafByte transport protocol and address family byte
|
||||||
|
*/
|
||||||
|
public static AddressFamily valueOf(byte tpafByte) {
|
||||||
|
int addressFamily = tpafByte & FAMILY_MASK;
|
||||||
|
switch((byte) addressFamily) {
|
||||||
|
case AF_IPV4_BYTE:
|
||||||
|
return AF_IPv4;
|
||||||
|
case AF_IPV6_BYTE:
|
||||||
|
return AF_IPv6;
|
||||||
|
case AF_UNSPEC_BYTE:
|
||||||
|
return AF_UNSPEC;
|
||||||
|
case AF_UNIX_BYTE:
|
||||||
|
return AF_UNIX;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("unknown address family: " + addressFamily);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the byte value of this address family.
|
||||||
|
*/
|
||||||
|
public byte byteValue() {
|
||||||
|
return byteValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transport protocol of an HAProxy proxy protocol header
|
||||||
|
*/
|
||||||
|
public enum TransportProtocol {
|
||||||
|
/**
|
||||||
|
* The UNSPEC transport protocol represents a connection which was forwarded for an unkown protocol.
|
||||||
|
*/
|
||||||
|
UNSPEC(TRANSPORT_UNSPEC_BYTE),
|
||||||
|
/**
|
||||||
|
* The STREAM transport protocol represents a connection which was forwarded for a TCP connection.
|
||||||
|
*/
|
||||||
|
STREAM(TRANSPORT_STREAM_BYTE),
|
||||||
|
/**
|
||||||
|
* The DGRAM transport protocol represents a connection which was forwarded for a UDP connection.
|
||||||
|
*/
|
||||||
|
DGRAM(TRANSPORT_DGRAM_BYTE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transport protocol is specified in the lowest 4 bits of the transport protocol and address family byte
|
||||||
|
*/
|
||||||
|
private static final byte TRANSPORT_MASK = 0x0f;
|
||||||
|
|
||||||
|
private final byte transportByte;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance.
|
||||||
|
*/
|
||||||
|
TransportProtocol(byte transportByte) {
|
||||||
|
this.transportByte = transportByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link TransportProtocol} represented by the lowest 4 bits of the specified byte.
|
||||||
|
*
|
||||||
|
* @param tpafByte transport protocol and address family byte
|
||||||
|
*/
|
||||||
|
public static TransportProtocol valueOf(byte tpafByte) {
|
||||||
|
int transportProtocol = tpafByte & TRANSPORT_MASK;
|
||||||
|
switch ((byte) transportProtocol) {
|
||||||
|
case TRANSPORT_STREAM_BYTE:
|
||||||
|
return STREAM;
|
||||||
|
case TRANSPORT_UNSPEC_BYTE:
|
||||||
|
return UNSPEC;
|
||||||
|
case TRANSPORT_DGRAM_BYTE:
|
||||||
|
return DGRAM;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("unknown transport protocol: " + transportProtocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the byte value of this transport protocol.
|
||||||
|
*/
|
||||||
|
public byte byteValue() {
|
||||||
|
return transportByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The address family of an HAProxy proxy protocol header
|
|
||||||
*/
|
|
||||||
public final class ProxiedAddressFamily implements Comparable<ProxiedAddressFamily> {
|
|
||||||
/**
|
|
||||||
* The highest 4 bits of the transport protocol and address family byte contain the address family
|
|
||||||
*/
|
|
||||||
private static final byte FAMILY_MASK = (byte) 0xf0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address family byte constants
|
|
||||||
*/
|
|
||||||
private static final byte UNSPECIFIED_BYTE = (byte) 0x00;
|
|
||||||
private static final byte IPV4_BYTE = (byte) 0x10;
|
|
||||||
private static final byte IPV6_BYTE = (byte) 0x20;
|
|
||||||
private static final byte UNIX_BYTE = (byte) 0x30;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UNSPECIFIED address family represents a connection which was forwarded for an unkown protocol
|
|
||||||
*/
|
|
||||||
public static final ProxiedAddressFamily UNSPECIFIED = new ProxiedAddressFamily("UNSPECIFIED", UNSPECIFIED_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The IPV4 address family represents a connection which was forwarded for an IPV4 client
|
|
||||||
*/
|
|
||||||
public static final ProxiedAddressFamily IPV4 = new ProxiedAddressFamily("IPV4", IPV4_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The IPV6 address family represents a connection which was forwarded for an IPV6 client
|
|
||||||
*/
|
|
||||||
public static final ProxiedAddressFamily IPV6 = new ProxiedAddressFamily("IPV6", IPV6_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UNIX address family represents a connection which was forwarded for a unix socket
|
|
||||||
*/
|
|
||||||
public static final ProxiedAddressFamily UNIX = new ProxiedAddressFamily("UNIX", UNIX_BYTE);
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final byte addressFamilyByte;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance
|
|
||||||
*/
|
|
||||||
private ProxiedAddressFamily(String name, byte addressFamilyByte) {
|
|
||||||
this.name = name;
|
|
||||||
this.addressFamilyByte = addressFamilyByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ProxiedAddressFamily} represented by the specified address family byte
|
|
||||||
*
|
|
||||||
* @param addressFamilyByte address family byte
|
|
||||||
* @return {@link ProxiedAddressFamily} instance OR {@code null} if the
|
|
||||||
* address family is not recognized
|
|
||||||
*/
|
|
||||||
public static ProxiedAddressFamily valueOf(byte addressFamilyByte) {
|
|
||||||
switch((byte) (addressFamilyByte & FAMILY_MASK)) {
|
|
||||||
case IPV4_BYTE:
|
|
||||||
return IPV4;
|
|
||||||
case IPV6_BYTE:
|
|
||||||
return IPV6;
|
|
||||||
case UNSPECIFIED_BYTE:
|
|
||||||
return UNSPECIFIED;
|
|
||||||
case UNIX_BYTE:
|
|
||||||
return UNIX;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this address family
|
|
||||||
*
|
|
||||||
* @return the name of this address family
|
|
||||||
*/
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte value of this address family
|
|
||||||
*
|
|
||||||
* @return the byte value of this address family
|
|
||||||
*/
|
|
||||||
public byte byteValue() {
|
|
||||||
return addressFamilyByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof ProxiedAddressFamily)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProxiedAddressFamily that = (ProxiedAddressFamily) o;
|
|
||||||
return byteValue() == that.byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(ProxiedAddressFamily o) {
|
|
||||||
return byteValue() - o.byteValue();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,207 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The protocol and address family of an HAProxy proxy protocol header
|
|
||||||
*/
|
|
||||||
public final class ProxiedProtocolAndFamily implements Comparable<ProxiedProtocolAndFamily> {
|
|
||||||
/**
|
|
||||||
* Protocol and address family byte constants
|
|
||||||
*/
|
|
||||||
private static final byte UNKNOWN_BYTE = (byte) 0x00;
|
|
||||||
private static final byte TCP4_BYTE = (byte) 0x11;
|
|
||||||
private static final byte TCP6_BYTE = (byte) 0x21;
|
|
||||||
private static final byte UDP4_BYTE = (byte) 0x12;
|
|
||||||
private static final byte UDP6_BYTE = (byte) 0x22;
|
|
||||||
private static final byte UNIX_STREAM_BYTE = (byte) 0x31;
|
|
||||||
private static final byte UNIX_DGRAM_BYTE = (byte) 0x32;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UNKNOWN protocol and address family represents a connection which was forwarded for an unknown protocol
|
|
||||||
* and address family
|
|
||||||
*/
|
|
||||||
public static final ProxiedProtocolAndFamily UNKNOWN = new ProxiedProtocolAndFamily(
|
|
||||||
"UNKNOWN", ProxiedAddressFamily.UNSPECIFIED, ProxiedTransportProtocol.UNSPECIFIED, UNKNOWN_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The TCP4 protocol and address family represents a connection which was forwarded for an IPV4 client over TCP
|
|
||||||
*/
|
|
||||||
public static final ProxiedProtocolAndFamily TCP4 = new ProxiedProtocolAndFamily(
|
|
||||||
"TCP4", ProxiedAddressFamily.IPV4, ProxiedTransportProtocol.STREAM, TCP4_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The TCP6 protocol and address family represents a connection which was forwarded for an IPV6 client over TCP
|
|
||||||
*/
|
|
||||||
public static final ProxiedProtocolAndFamily TCP6 = new ProxiedProtocolAndFamily(
|
|
||||||
"TCP6", ProxiedAddressFamily.IPV6, ProxiedTransportProtocol.STREAM, TCP6_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UDP4 protocol and address family represents a connection which was forwarded for an IPV4 client over UDP
|
|
||||||
*/
|
|
||||||
public static final ProxiedProtocolAndFamily UDP4 = new ProxiedProtocolAndFamily(
|
|
||||||
"UDP4", ProxiedAddressFamily.IPV4, ProxiedTransportProtocol.DGRAM, UDP4_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UDP6 protocol and address family represents a connection which was forwarded for an IPV6 client over UDP
|
|
||||||
*/
|
|
||||||
public static final ProxiedProtocolAndFamily UDP6 = new ProxiedProtocolAndFamily(
|
|
||||||
"UDP6", ProxiedAddressFamily.IPV6, ProxiedTransportProtocol.DGRAM, UDP6_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UNIX_STREAM protocol and address family represents a connection which was forwarded for a unix stream socket
|
|
||||||
*/
|
|
||||||
public static final ProxiedProtocolAndFamily UNIX_STREAM = new ProxiedProtocolAndFamily(
|
|
||||||
"UNIX_STREAM", ProxiedAddressFamily.UNIX, ProxiedTransportProtocol.STREAM, UNIX_STREAM_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UNIX_DGRAM protocol and address family represents a connection which was forwarded for a unix datagram socket
|
|
||||||
*/
|
|
||||||
public static final ProxiedProtocolAndFamily UNIX_DGRAM = new ProxiedProtocolAndFamily(
|
|
||||||
"UNIX_DGRAM", ProxiedAddressFamily.UNIX, ProxiedTransportProtocol.DGRAM, UNIX_DGRAM_BYTE);
|
|
||||||
|
|
||||||
private static final Map<String, ProxiedProtocolAndFamily> PROTO_AND_FAMILY_NAME_MAP =
|
|
||||||
new HashMap<String, ProxiedProtocolAndFamily>(7);
|
|
||||||
|
|
||||||
static {
|
|
||||||
PROTO_AND_FAMILY_NAME_MAP.put(UNKNOWN.name(), UNKNOWN);
|
|
||||||
PROTO_AND_FAMILY_NAME_MAP.put(TCP4.name(), TCP4);
|
|
||||||
PROTO_AND_FAMILY_NAME_MAP.put(TCP6.name(), TCP6);
|
|
||||||
PROTO_AND_FAMILY_NAME_MAP.put(UDP4.name(), UDP4);
|
|
||||||
PROTO_AND_FAMILY_NAME_MAP.put(UDP6.name(), UDP6);
|
|
||||||
PROTO_AND_FAMILY_NAME_MAP.put(UNIX_STREAM.name(), UNIX_STREAM);
|
|
||||||
PROTO_AND_FAMILY_NAME_MAP.put(UNIX_DGRAM.name(), UNIX_DGRAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final byte pafByte;
|
|
||||||
private final ProxiedAddressFamily addressFamily;
|
|
||||||
private final ProxiedTransportProtocol transportProtocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance
|
|
||||||
*/
|
|
||||||
private ProxiedProtocolAndFamily(String name, ProxiedAddressFamily addressFamily,
|
|
||||||
ProxiedTransportProtocol transportProtocol, byte pafByte) {
|
|
||||||
this.name = name;
|
|
||||||
this.pafByte = pafByte;
|
|
||||||
this.addressFamily = addressFamily;
|
|
||||||
this.transportProtocol = transportProtocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ProxiedProtocolAndFamily} represented by the specified name
|
|
||||||
*
|
|
||||||
* @param name protocol and address family name
|
|
||||||
* @return {@link ProxiedProtocolAndFamily} instance OR {@code null} if the
|
|
||||||
* name is not recognized
|
|
||||||
*/
|
|
||||||
public static ProxiedProtocolAndFamily valueOf(String name) {
|
|
||||||
return PROTO_AND_FAMILY_NAME_MAP.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ProxiedProtocolAndFamily} represented by the protocol and family byte
|
|
||||||
*
|
|
||||||
* @param pafByte protocol and address family byte
|
|
||||||
* @return {@link ProxiedProtocolAndFamily} instance OR {@code null} if the
|
|
||||||
* protocol and address family byte is not recognized
|
|
||||||
*/
|
|
||||||
public static ProxiedProtocolAndFamily valueOf(byte pafByte) {
|
|
||||||
switch (pafByte) {
|
|
||||||
case TCP4_BYTE:
|
|
||||||
return TCP4;
|
|
||||||
case TCP6_BYTE:
|
|
||||||
return TCP6;
|
|
||||||
case UNKNOWN_BYTE:
|
|
||||||
return UNKNOWN;
|
|
||||||
case UDP4_BYTE:
|
|
||||||
return UDP4;
|
|
||||||
case UDP6_BYTE:
|
|
||||||
return UDP6;
|
|
||||||
case UNIX_STREAM_BYTE:
|
|
||||||
return UNIX_STREAM;
|
|
||||||
case UNIX_DGRAM_BYTE:
|
|
||||||
return UNIX_DGRAM;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this protocol and address family
|
|
||||||
*
|
|
||||||
* @return the name of this protocol and address family
|
|
||||||
*/
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte value of this protocol and address family
|
|
||||||
*
|
|
||||||
* @return the byte value of this protocol and address family
|
|
||||||
*/
|
|
||||||
public byte byteValue() {
|
|
||||||
return pafByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ProxiedAddressFamily} of this protocol and address family
|
|
||||||
*
|
|
||||||
* @return the address family
|
|
||||||
*/
|
|
||||||
public ProxiedAddressFamily proxiedAddressFamily() {
|
|
||||||
return addressFamily;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ProxiedTransportProtocol} of this protocol and address family
|
|
||||||
*
|
|
||||||
* @return the transport protocol
|
|
||||||
*/
|
|
||||||
public ProxiedTransportProtocol proxiedTransportProtocol() {
|
|
||||||
return transportProtocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return name().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof ProxiedProtocolAndFamily)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProxiedProtocolAndFamily that = (ProxiedProtocolAndFamily) o;
|
|
||||||
return name().equals(that.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(ProxiedProtocolAndFamily o) {
|
|
||||||
return name().compareTo(o.name());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The transport protocol of an HAProxy proxy protocol header
|
|
||||||
*/
|
|
||||||
public final class ProxiedTransportProtocol implements Comparable<ProxiedTransportProtocol> {
|
|
||||||
/**
|
|
||||||
* The transport protocol is specified in the lowest 4 bits of the transport protocol and address family byte
|
|
||||||
*/
|
|
||||||
private static final byte TRANSPORT_MASK = (byte) 0x0f;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport Protocol byte constants
|
|
||||||
*/
|
|
||||||
private static final byte UNSPECIFIED_BYTE = (byte) 0x00;
|
|
||||||
private static final byte STREAM_BYTE = (byte) 0x01;
|
|
||||||
private static final byte DGRAM_BYTE = (byte) 0x02;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The UNSPECIFIED transport protocol represents a connection which was forwarded for an unkown protocol
|
|
||||||
*/
|
|
||||||
public static final ProxiedTransportProtocol UNSPECIFIED = new ProxiedTransportProtocol(
|
|
||||||
"UNSPECIFIED", UNSPECIFIED_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The STREAM transport protocol represents a connection which was forwarded for a TCP connection
|
|
||||||
*/
|
|
||||||
public static final ProxiedTransportProtocol STREAM = new ProxiedTransportProtocol("STREAM", STREAM_BYTE);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The DGRAM transport protocol represents a connection which was forwarded for a UDP connection
|
|
||||||
*/
|
|
||||||
public static final ProxiedTransportProtocol DGRAM = new ProxiedTransportProtocol("DGRAM", DGRAM_BYTE);
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final byte transportByte;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance
|
|
||||||
*/
|
|
||||||
private ProxiedTransportProtocol(String name, byte transportByte) {
|
|
||||||
this.name = name;
|
|
||||||
this.transportByte = transportByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ProxiedTransportProtocol} represented by the specified transport protocol byte
|
|
||||||
*
|
|
||||||
* @param addressFamilyByte transport protocol byte
|
|
||||||
* @return {@link ProxiedTransportProtocol} instance OR {@code null} if the
|
|
||||||
* transport protocol is not recognized
|
|
||||||
*/
|
|
||||||
public static ProxiedTransportProtocol valueOf(byte transportByte) {
|
|
||||||
switch ((byte) (transportByte & TRANSPORT_MASK)) {
|
|
||||||
case STREAM_BYTE:
|
|
||||||
return STREAM;
|
|
||||||
case UNSPECIFIED_BYTE:
|
|
||||||
return UNSPECIFIED;
|
|
||||||
case DGRAM_BYTE:
|
|
||||||
return DGRAM;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of this transport protocol
|
|
||||||
*
|
|
||||||
* @return the name of this transport protocol
|
|
||||||
*/
|
|
||||||
public String name() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte value of this transport protocol
|
|
||||||
*
|
|
||||||
* @return the byte value of this transport protocol
|
|
||||||
*/
|
|
||||||
public byte byteValue() {
|
|
||||||
return transportByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof ProxiedTransportProtocol)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProxiedTransportProtocol that = (ProxiedTransportProtocol) o;
|
|
||||||
return byteValue() == that.byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(ProxiedTransportProtocol o) {
|
|
||||||
return byteValue() - o.byteValue();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,899 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
|
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol.AddressFamily;
|
||||||
|
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol.TransportProtocol;
|
||||||
|
import io.netty.util.CharsetUtil;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static io.netty.buffer.Unpooled.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class HAProxyMessageDecoderTest {
|
||||||
|
|
||||||
|
private EmbeddedChannel ch;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
ch = new EmbeddedChannel(new HAProxyMessageDecoder());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIPV4Decode() {
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V1, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.TCP4, msg.proxiedProtocol());
|
||||||
|
assertEquals("192.168.0.1", msg.sourceAddress());
|
||||||
|
assertEquals("192.168.0.11", msg.destinationAddress());
|
||||||
|
assertEquals(56324, msg.sourcePort());
|
||||||
|
assertEquals(443, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIPV6Decode() {
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
String header = "PROXY TCP6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 1050:0:0:0:5:600:300c:326b 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V1, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.TCP6, msg.proxiedProtocol());
|
||||||
|
assertEquals("2001:0db8:85a3:0000:0000:8a2e:0370:7334", msg.sourceAddress());
|
||||||
|
assertEquals("1050:0:0:0:5:600:300c:326b", msg.destinationAddress());
|
||||||
|
assertEquals(56324, msg.sourcePort());
|
||||||
|
assertEquals(443, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnknownProtocolDecode() {
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
String header = "PROXY UNKNOWN 192.168.0.1 192.168.0.11 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V1, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.UNKNOWN, msg.proxiedProtocol());
|
||||||
|
assertNull(msg.sourceAddress());
|
||||||
|
assertNull(msg.destinationAddress());
|
||||||
|
assertEquals(0, msg.sourcePort());
|
||||||
|
assertEquals(0, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testV1NoUDP() {
|
||||||
|
String header = "PROXY UDP4 192.168.0.1 192.168.0.11 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testInvalidPort() {
|
||||||
|
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 80000 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testInvalidIPV4Address() {
|
||||||
|
String header = "PROXY TCP4 299.168.0.1 192.168.0.11 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testInvalidIPV6Address() {
|
||||||
|
String header = "PROXY TCP6 r001:0db8:85a3:0000:0000:8a2e:0370:7334 1050:0:0:0:5:600:300c:326b 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testInvalidProtocol() {
|
||||||
|
String header = "PROXY TCP7 192.168.0.1 192.168.0.11 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testMissingParams() {
|
||||||
|
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testTooManyParams() {
|
||||||
|
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443 123\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testInvalidCommand() {
|
||||||
|
String header = "PING TCP4 192.168.0.1 192.168.0.11 56324 443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testInvalidEOL() {
|
||||||
|
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\nGET / HTTP/1.1\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testHeaderTooLong() {
|
||||||
|
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 " +
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000443\r\n";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIncompleteHeader() {
|
||||||
|
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324";
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCloseOnInvalid() {
|
||||||
|
ChannelFuture closeFuture = ch.closeFuture();
|
||||||
|
String header = "GET / HTTP/1.1\r\n";
|
||||||
|
try {
|
||||||
|
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
||||||
|
} catch (HAProxyProtocolException ppex) {
|
||||||
|
// swallow this exception since we're just testing to be sure the channel was closed
|
||||||
|
}
|
||||||
|
boolean isComplete = closeFuture.awaitUninterruptibly(5000);
|
||||||
|
if (!isComplete || !closeFuture.isDone() || !closeFuture.isSuccess()) {
|
||||||
|
fail("Expected channel close");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransportProtocolAndAddressFamily() {
|
||||||
|
final byte unkown = HAProxyProxiedProtocol.UNKNOWN.byteValue();
|
||||||
|
final byte tcp4 = HAProxyProxiedProtocol.TCP4.byteValue();
|
||||||
|
final byte tcp6 = HAProxyProxiedProtocol.TCP6.byteValue();
|
||||||
|
final byte udp4 = HAProxyProxiedProtocol.UDP4.byteValue();
|
||||||
|
final byte udp6 = HAProxyProxiedProtocol.UDP6.byteValue();
|
||||||
|
final byte unix_stream = HAProxyProxiedProtocol.UNIX_STREAM.byteValue();
|
||||||
|
final byte unix_dgram = HAProxyProxiedProtocol.UNIX_DGRAM.byteValue();
|
||||||
|
|
||||||
|
assertEquals(TransportProtocol.UNSPEC, TransportProtocol.valueOf(unkown));
|
||||||
|
assertEquals(TransportProtocol.STREAM, TransportProtocol.valueOf(tcp4));
|
||||||
|
assertEquals(TransportProtocol.STREAM, TransportProtocol.valueOf(tcp6));
|
||||||
|
assertEquals(TransportProtocol.STREAM, TransportProtocol.valueOf(unix_stream));
|
||||||
|
assertEquals(TransportProtocol.DGRAM, TransportProtocol.valueOf(udp4));
|
||||||
|
assertEquals(TransportProtocol.DGRAM, TransportProtocol.valueOf(udp6));
|
||||||
|
assertEquals(TransportProtocol.DGRAM, TransportProtocol.valueOf(unix_dgram));
|
||||||
|
|
||||||
|
assertEquals(AddressFamily.AF_UNSPEC, AddressFamily.valueOf(unkown));
|
||||||
|
assertEquals(AddressFamily.AF_IPv4, AddressFamily.valueOf(tcp4));
|
||||||
|
assertEquals(AddressFamily.AF_IPv4, AddressFamily.valueOf(udp4));
|
||||||
|
assertEquals(AddressFamily.AF_IPv6, AddressFamily.valueOf(tcp6));
|
||||||
|
assertEquals(AddressFamily.AF_IPv6, AddressFamily.valueOf(udp6));
|
||||||
|
assertEquals(AddressFamily.AF_UNIX, AddressFamily.valueOf(unix_stream));
|
||||||
|
assertEquals(AddressFamily.AF_UNIX, AddressFamily.valueOf(unix_dgram));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testV2IPV4Decode() {
|
||||||
|
byte[] header = new byte[28];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x11; // TCP over IPv4
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0c; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V2, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.TCP4, msg.proxiedProtocol());
|
||||||
|
assertEquals("192.168.0.1", msg.sourceAddress());
|
||||||
|
assertEquals("192.168.0.11", msg.destinationAddress());
|
||||||
|
assertEquals(56324, msg.sourcePort());
|
||||||
|
assertEquals(443, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testV2UDPDecode() {
|
||||||
|
byte[] header = new byte[28];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x12; // UDP over IPv4
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0c; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V2, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.UDP4, msg.proxiedProtocol());
|
||||||
|
assertEquals("192.168.0.1", msg.sourceAddress());
|
||||||
|
assertEquals("192.168.0.11", msg.destinationAddress());
|
||||||
|
assertEquals(56324, msg.sourcePort());
|
||||||
|
assertEquals(443, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testv2IPV6Decode() {
|
||||||
|
byte[] header = new byte[52];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x21; // TCP over IPv6
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x24; // -----
|
||||||
|
|
||||||
|
header[16] = 0x20; // Source Address
|
||||||
|
header[17] = 0x01; // -----
|
||||||
|
header[18] = 0x0d; // -----
|
||||||
|
header[19] = (byte) 0xb8; // -----
|
||||||
|
header[20] = (byte) 0x85; // -----
|
||||||
|
header[21] = (byte) 0xa3; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x00; // -----
|
||||||
|
header[24] = 0x00; // -----
|
||||||
|
header[25] = 0x00; // -----
|
||||||
|
header[26] = (byte) 0x8a; // -----
|
||||||
|
header[27] = 0x2e; // -----
|
||||||
|
header[28] = 0x03; // -----
|
||||||
|
header[29] = 0x70; // -----
|
||||||
|
header[30] = 0x73; // -----
|
||||||
|
header[31] = 0x34; // -----
|
||||||
|
|
||||||
|
header[32] = 0x10; // Destination Address
|
||||||
|
header[33] = 0x50; // -----
|
||||||
|
header[34] = 0x00; // -----
|
||||||
|
header[35] = 0x00; // -----
|
||||||
|
header[36] = 0x00; // -----
|
||||||
|
header[37] = 0x00; // -----
|
||||||
|
header[38] = 0x00; // -----
|
||||||
|
header[39] = 0x00; // -----
|
||||||
|
header[40] = 0x00; // -----
|
||||||
|
header[41] = 0x05; // -----
|
||||||
|
header[42] = 0x06; // -----
|
||||||
|
header[43] = 0x00; // -----
|
||||||
|
header[44] = 0x30; // -----
|
||||||
|
header[45] = 0x0c; // -----
|
||||||
|
header[46] = 0x32; // -----
|
||||||
|
header[47] = 0x6b; // -----
|
||||||
|
|
||||||
|
header[48] = (byte) 0xdc; // Source Port
|
||||||
|
header[49] = 0x04; // -----
|
||||||
|
|
||||||
|
header[50] = 0x01; // Destination Port
|
||||||
|
header[51] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V2, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.TCP6, msg.proxiedProtocol());
|
||||||
|
assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", msg.sourceAddress());
|
||||||
|
assertEquals("1050:0:0:0:5:600:300c:326b", msg.destinationAddress());
|
||||||
|
assertEquals(56324, msg.sourcePort());
|
||||||
|
assertEquals(443, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testv2UnixDecode() {
|
||||||
|
byte[] header = new byte[232];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x31; // UNIX_STREAM
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = (byte) 0xd8; // -----
|
||||||
|
|
||||||
|
header[16] = 0x2f; // Source Address
|
||||||
|
header[17] = 0x76; // -----
|
||||||
|
header[18] = 0x61; // -----
|
||||||
|
header[19] = 0x72; // -----
|
||||||
|
header[20] = 0x2f; // -----
|
||||||
|
header[21] = 0x72; // -----
|
||||||
|
header[22] = 0x75; // -----
|
||||||
|
header[23] = 0x6e; // -----
|
||||||
|
header[24] = 0x2f; // -----
|
||||||
|
header[25] = 0x73; // -----
|
||||||
|
header[26] = 0x72; // -----
|
||||||
|
header[27] = 0x63; // -----
|
||||||
|
header[28] = 0x2e; // -----
|
||||||
|
header[29] = 0x73; // -----
|
||||||
|
header[30] = 0x6f; // -----
|
||||||
|
header[31] = 0x63; // -----
|
||||||
|
header[32] = 0x6b; // -----
|
||||||
|
header[33] = 0x00; // -----
|
||||||
|
|
||||||
|
header[124] = 0x2f; // Destination Address
|
||||||
|
header[125] = 0x76; // -----
|
||||||
|
header[126] = 0x61; // -----
|
||||||
|
header[127] = 0x72; // -----
|
||||||
|
header[128] = 0x2f; // -----
|
||||||
|
header[129] = 0x72; // -----
|
||||||
|
header[130] = 0x75; // -----
|
||||||
|
header[131] = 0x6e; // -----
|
||||||
|
header[132] = 0x2f; // -----
|
||||||
|
header[133] = 0x64; // -----
|
||||||
|
header[134] = 0x65; // -----
|
||||||
|
header[135] = 0x73; // -----
|
||||||
|
header[136] = 0x74; // -----
|
||||||
|
header[137] = 0x2e; // -----
|
||||||
|
header[138] = 0x73; // -----
|
||||||
|
header[139] = 0x6f; // -----
|
||||||
|
header[140] = 0x63; // -----
|
||||||
|
header[141] = 0x6b; // -----
|
||||||
|
header[142] = 0x00; // -----
|
||||||
|
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V2, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.UNIX_STREAM, msg.proxiedProtocol());
|
||||||
|
assertEquals("/var/run/src.sock", msg.sourceAddress());
|
||||||
|
assertEquals("/var/run/dest.sock", msg.destinationAddress());
|
||||||
|
assertEquals(0, msg.sourcePort());
|
||||||
|
assertEquals(0, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testV2LocalProtocolDecode() {
|
||||||
|
byte[] header = new byte[28];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x20; // v2, cmd=LOCAL
|
||||||
|
header[13] = 0x00; // Unspecified transport protocol and address family
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0c; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V2, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.LOCAL, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.UNKNOWN, msg.proxiedProtocol());
|
||||||
|
assertNull(msg.sourceAddress());
|
||||||
|
assertNull(msg.destinationAddress());
|
||||||
|
assertEquals(0, msg.sourcePort());
|
||||||
|
assertEquals(0, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testV2UnknownProtocolDecode() {
|
||||||
|
byte[] header = new byte[28];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x00; // Unspecified transport protocol and address family
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0c; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V2, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.UNKNOWN, msg.proxiedProtocol());
|
||||||
|
assertNull(msg.sourceAddress());
|
||||||
|
assertNull(msg.destinationAddress());
|
||||||
|
assertEquals(0, msg.sourcePort());
|
||||||
|
assertEquals(0, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testV2WithTLV() {
|
||||||
|
ch = new EmbeddedChannel(new HAProxyMessageDecoder(4));
|
||||||
|
|
||||||
|
byte[] header = new byte[236];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x31; // UNIX_STREAM
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = (byte) 0xdc; // -----
|
||||||
|
|
||||||
|
header[16] = 0x2f; // Source Address
|
||||||
|
header[17] = 0x76; // -----
|
||||||
|
header[18] = 0x61; // -----
|
||||||
|
header[19] = 0x72; // -----
|
||||||
|
header[20] = 0x2f; // -----
|
||||||
|
header[21] = 0x72; // -----
|
||||||
|
header[22] = 0x75; // -----
|
||||||
|
header[23] = 0x6e; // -----
|
||||||
|
header[24] = 0x2f; // -----
|
||||||
|
header[25] = 0x73; // -----
|
||||||
|
header[26] = 0x72; // -----
|
||||||
|
header[27] = 0x63; // -----
|
||||||
|
header[28] = 0x2e; // -----
|
||||||
|
header[29] = 0x73; // -----
|
||||||
|
header[30] = 0x6f; // -----
|
||||||
|
header[31] = 0x63; // -----
|
||||||
|
header[32] = 0x6b; // -----
|
||||||
|
header[33] = 0x00; // -----
|
||||||
|
|
||||||
|
header[124] = 0x2f; // Destination Address
|
||||||
|
header[125] = 0x76; // -----
|
||||||
|
header[126] = 0x61; // -----
|
||||||
|
header[127] = 0x72; // -----
|
||||||
|
header[128] = 0x2f; // -----
|
||||||
|
header[129] = 0x72; // -----
|
||||||
|
header[130] = 0x75; // -----
|
||||||
|
header[131] = 0x6e; // -----
|
||||||
|
header[132] = 0x2f; // -----
|
||||||
|
header[133] = 0x64; // -----
|
||||||
|
header[134] = 0x65; // -----
|
||||||
|
header[135] = 0x73; // -----
|
||||||
|
header[136] = 0x74; // -----
|
||||||
|
header[137] = 0x2e; // -----
|
||||||
|
header[138] = 0x73; // -----
|
||||||
|
header[139] = 0x6f; // -----
|
||||||
|
header[140] = 0x63; // -----
|
||||||
|
header[141] = 0x6b; // -----
|
||||||
|
header[142] = 0x00; // -----
|
||||||
|
|
||||||
|
// ---- Additional data (TLV) ---- \\
|
||||||
|
|
||||||
|
header[232] = 0x01; // Type
|
||||||
|
header[233] = 0x00; // Remaining bytes
|
||||||
|
header[234] = 0x01; // -----
|
||||||
|
header[235] = 0x01; // Payload
|
||||||
|
|
||||||
|
int startChannels = ch.pipeline().names().size();
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
Object msgObj = ch.readInbound();
|
||||||
|
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
||||||
|
assertTrue(msgObj instanceof HAProxyMessage);
|
||||||
|
HAProxyMessage msg = (HAProxyMessage) msgObj;
|
||||||
|
assertEquals(HAProxyProtocolVersion.V2, msg.protocolVersion());
|
||||||
|
assertEquals(HAProxyCommand.PROXY, msg.command());
|
||||||
|
assertEquals(HAProxyProxiedProtocol.UNIX_STREAM, msg.proxiedProtocol());
|
||||||
|
assertEquals("/var/run/src.sock", msg.sourceAddress());
|
||||||
|
assertEquals("/var/run/dest.sock", msg.destinationAddress());
|
||||||
|
assertEquals(0, msg.sourcePort());
|
||||||
|
assertEquals(0, msg.destinationPort());
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testV2InvalidProtocol() {
|
||||||
|
byte[] header = new byte[28];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x41; // Bogus transport protocol
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0c; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testV2MissingParams() {
|
||||||
|
byte[] header = new byte[26];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x11; // TCP over IPv4
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0a; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testV2InvalidCommand() {
|
||||||
|
byte[] header = new byte[28];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x22; // v2, Bogus command
|
||||||
|
header[13] = 0x11; // TCP over IPv4
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0c; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testV2InvalidVersion() {
|
||||||
|
byte[] header = new byte[28];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x31; // Bogus version, cmd=PROXY
|
||||||
|
header[13] = 0x11; // TCP over IPv4
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = 0x0c; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = HAProxyProtocolException.class)
|
||||||
|
public void testV2HeaderTooLong() {
|
||||||
|
ch = new EmbeddedChannel(new HAProxyMessageDecoder(0));
|
||||||
|
|
||||||
|
byte[] header = new byte[248];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
header[13] = 0x11; // TCP over IPv4
|
||||||
|
|
||||||
|
header[14] = 0x00; // Remaining Bytes
|
||||||
|
header[15] = (byte) 0xe8; // -----
|
||||||
|
|
||||||
|
header[16] = (byte) 0xc0; // Source Address
|
||||||
|
header[17] = (byte) 0xa8; // -----
|
||||||
|
header[18] = 0x00; // -----
|
||||||
|
header[19] = 0x01; // -----
|
||||||
|
|
||||||
|
header[20] = (byte) 0xc0; // Destination Address
|
||||||
|
header[21] = (byte) 0xa8; // -----
|
||||||
|
header[22] = 0x00; // -----
|
||||||
|
header[23] = 0x0b; // -----
|
||||||
|
|
||||||
|
header[24] = (byte) 0xdc; // Source Port
|
||||||
|
header[25] = 0x04; // -----
|
||||||
|
|
||||||
|
header[26] = 0x01; // Destination Port
|
||||||
|
header[27] = (byte) 0xbb; // -----
|
||||||
|
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testV2IncompleteHeader() {
|
||||||
|
byte[] header = new byte[13];
|
||||||
|
header[0] = 0x0D; // Binary Prefix
|
||||||
|
header[1] = 0x0A; // -----
|
||||||
|
header[2] = 0x0D; // -----
|
||||||
|
header[3] = 0x0A; // -----
|
||||||
|
header[4] = 0x00; // -----
|
||||||
|
header[5] = 0x0D; // -----
|
||||||
|
header[6] = 0x0A; // -----
|
||||||
|
header[7] = 0x51; // -----
|
||||||
|
header[8] = 0x55; // -----
|
||||||
|
header[9] = 0x49; // -----
|
||||||
|
header[10] = 0x54; // -----
|
||||||
|
header[11] = 0x0A; // -----
|
||||||
|
|
||||||
|
header[12] = 0x21; // v2, cmd=PROXY
|
||||||
|
|
||||||
|
ch.writeInbound(copiedBuffer(header));
|
||||||
|
assertNull(ch.readInbound());
|
||||||
|
assertFalse(ch.finish());
|
||||||
|
}
|
||||||
|
}
|
@ -1,903 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 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 io.netty.handler.codec.haproxy;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
|
||||||
import io.netty.util.CharsetUtil;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static io.netty.buffer.Unpooled.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
public class HAProxyProtocolDecoderTest {
|
|
||||||
|
|
||||||
private EmbeddedChannel ch;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
ch = new EmbeddedChannel(new HAProxyProtocolDecoder());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIPV4Decode() {
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.ONE, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.TCP4, msg.protocolAndFamily());
|
|
||||||
assertEquals("192.168.0.1", msg.sourceAddress());
|
|
||||||
assertEquals("192.168.0.11", msg.destinationAddress());
|
|
||||||
assertEquals(56324, msg.sourcePort());
|
|
||||||
assertEquals(443, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIPV6Decode() {
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
String header = "PROXY TCP6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 1050:0:0:0:5:600:300c:326b 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.ONE, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.TCP6, msg.protocolAndFamily());
|
|
||||||
assertEquals("2001:0db8:85a3:0000:0000:8a2e:0370:7334", msg.sourceAddress());
|
|
||||||
assertEquals("1050:0:0:0:5:600:300c:326b", msg.destinationAddress());
|
|
||||||
assertEquals(56324, msg.sourcePort());
|
|
||||||
assertEquals(443, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUnknownProtocolDecode() {
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
String header = "PROXY UNKNOWN 192.168.0.1 192.168.0.11 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.ONE, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.UNKNOWN, msg.protocolAndFamily());
|
|
||||||
assertNull(msg.sourceAddress());
|
|
||||||
assertNull(msg.destinationAddress());
|
|
||||||
assertEquals(0, msg.sourcePort());
|
|
||||||
assertEquals(0, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testV1NoUDP() {
|
|
||||||
String header = "PROXY UDP4 192.168.0.1 192.168.0.11 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testInvalidPort() {
|
|
||||||
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 80000 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testInvalidIPV4Address() {
|
|
||||||
String header = "PROXY TCP4 299.168.0.1 192.168.0.11 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testInvalidIPV6Address() {
|
|
||||||
String header = "PROXY TCP6 r001:0db8:85a3:0000:0000:8a2e:0370:7334 1050:0:0:0:5:600:300c:326b 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testInvalidProtocol() {
|
|
||||||
String header = "PROXY TCP7 192.168.0.1 192.168.0.11 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testMissingParams() {
|
|
||||||
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testTooManyParams() {
|
|
||||||
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443 123\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testInvalidCommand() {
|
|
||||||
String header = "PING TCP4 192.168.0.1 192.168.0.11 56324 443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testInvalidEOL() {
|
|
||||||
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\nGET / HTTP/1.1\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testHeaderTooLong() {
|
|
||||||
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324 " +
|
|
||||||
"00000000000000000000000000000000000000000000000000000000000000000443\r\n";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIncompleteHeader() {
|
|
||||||
String header = "PROXY TCP4 192.168.0.1 192.168.0.11 56324";
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCloseOnInvalid() {
|
|
||||||
ChannelFuture closeFuture = ch.closeFuture();
|
|
||||||
String header = "GET / HTTP/1.1\r\n";
|
|
||||||
try {
|
|
||||||
ch.writeInbound(copiedBuffer(header, CharsetUtil.US_ASCII));
|
|
||||||
} catch (HAProxyProtocolException ppex) {
|
|
||||||
// swallow this exception since we're just testing to be sure the channel was closed
|
|
||||||
}
|
|
||||||
boolean isComplete = closeFuture.awaitUninterruptibly(5000);
|
|
||||||
if (!isComplete || !closeFuture.isDone() || !closeFuture.isSuccess()) {
|
|
||||||
fail("Expected channel close");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransportProtocolAndAddressFamily() {
|
|
||||||
final byte unkown = ProxiedProtocolAndFamily.UNKNOWN.byteValue();
|
|
||||||
final byte tcp4 = ProxiedProtocolAndFamily.TCP4.byteValue();
|
|
||||||
final byte tcp6 = ProxiedProtocolAndFamily.TCP6.byteValue();
|
|
||||||
final byte udp4 = ProxiedProtocolAndFamily.UDP4.byteValue();
|
|
||||||
final byte udp6 = ProxiedProtocolAndFamily.UDP6.byteValue();
|
|
||||||
final byte unix_stream = ProxiedProtocolAndFamily.UNIX_STREAM.byteValue();
|
|
||||||
final byte unix_dgram = ProxiedProtocolAndFamily.UNIX_DGRAM.byteValue();
|
|
||||||
|
|
||||||
assertEquals(ProxiedTransportProtocol.UNSPECIFIED, ProxiedTransportProtocol.valueOf(unkown));
|
|
||||||
assertEquals(ProxiedTransportProtocol.STREAM, ProxiedTransportProtocol.valueOf(tcp4));
|
|
||||||
assertEquals(ProxiedTransportProtocol.STREAM, ProxiedTransportProtocol.valueOf(tcp6));
|
|
||||||
assertEquals(ProxiedTransportProtocol.STREAM, ProxiedTransportProtocol.valueOf(unix_stream));
|
|
||||||
assertEquals(ProxiedTransportProtocol.DGRAM, ProxiedTransportProtocol.valueOf(udp4));
|
|
||||||
assertEquals(ProxiedTransportProtocol.DGRAM, ProxiedTransportProtocol.valueOf(udp6));
|
|
||||||
assertEquals(ProxiedTransportProtocol.DGRAM, ProxiedTransportProtocol.valueOf(unix_dgram));
|
|
||||||
|
|
||||||
assertEquals(ProxiedAddressFamily.UNSPECIFIED, ProxiedAddressFamily.valueOf(unkown));
|
|
||||||
assertEquals(ProxiedAddressFamily.IPV4, ProxiedAddressFamily.valueOf(tcp4));
|
|
||||||
assertEquals(ProxiedAddressFamily.IPV4, ProxiedAddressFamily.valueOf(udp4));
|
|
||||||
assertEquals(ProxiedAddressFamily.IPV6, ProxiedAddressFamily.valueOf(tcp6));
|
|
||||||
assertEquals(ProxiedAddressFamily.IPV6, ProxiedAddressFamily.valueOf(udp6));
|
|
||||||
assertEquals(ProxiedAddressFamily.UNIX, ProxiedAddressFamily.valueOf(unix_stream));
|
|
||||||
assertEquals(ProxiedAddressFamily.UNIX, ProxiedAddressFamily.valueOf(unix_dgram));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testV2IPV4Decode() {
|
|
||||||
byte[] header = new byte[28];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x11; // TCP over IPv4
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0c; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.TWO, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.TCP4, msg.protocolAndFamily());
|
|
||||||
assertEquals("192.168.0.1", msg.sourceAddress());
|
|
||||||
assertEquals("192.168.0.11", msg.destinationAddress());
|
|
||||||
assertEquals(56324, msg.sourcePort());
|
|
||||||
assertEquals(443, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testV2UDPDecode() {
|
|
||||||
byte[] header = new byte[28];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x12; // UDP over IPv4
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0c; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.TWO, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.UDP4, msg.protocolAndFamily());
|
|
||||||
assertEquals("192.168.0.1", msg.sourceAddress());
|
|
||||||
assertEquals("192.168.0.11", msg.destinationAddress());
|
|
||||||
assertEquals(56324, msg.sourcePort());
|
|
||||||
assertEquals(443, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testv2IPV6Decode() {
|
|
||||||
byte[] header = new byte[52];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x21; // TCP over IPv6
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x24; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0x20; // Source Address
|
|
||||||
header[17] = (byte) 0x01; // -----
|
|
||||||
header[18] = (byte) 0x0d; // -----
|
|
||||||
header[19] = (byte) 0xb8; // -----
|
|
||||||
header[20] = (byte) 0x85; // -----
|
|
||||||
header[21] = (byte) 0xa3; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x00; // -----
|
|
||||||
header[24] = (byte) 0x00; // -----
|
|
||||||
header[25] = (byte) 0x00; // -----
|
|
||||||
header[26] = (byte) 0x8a; // -----
|
|
||||||
header[27] = (byte) 0x2e; // -----
|
|
||||||
header[28] = (byte) 0x03; // -----
|
|
||||||
header[29] = (byte) 0x70; // -----
|
|
||||||
header[30] = (byte) 0x73; // -----
|
|
||||||
header[31] = (byte) 0x34; // -----
|
|
||||||
|
|
||||||
header[32] = (byte) 0x10; // Destination Address
|
|
||||||
header[33] = (byte) 0x50; // -----
|
|
||||||
header[34] = (byte) 0x00; // -----
|
|
||||||
header[35] = (byte) 0x00; // -----
|
|
||||||
header[36] = (byte) 0x00; // -----
|
|
||||||
header[37] = (byte) 0x00; // -----
|
|
||||||
header[38] = (byte) 0x00; // -----
|
|
||||||
header[39] = (byte) 0x00; // -----
|
|
||||||
header[40] = (byte) 0x00; // -----
|
|
||||||
header[41] = (byte) 0x05; // -----
|
|
||||||
header[42] = (byte) 0x06; // -----
|
|
||||||
header[43] = (byte) 0x00; // -----
|
|
||||||
header[44] = (byte) 0x30; // -----
|
|
||||||
header[45] = (byte) 0x0c; // -----
|
|
||||||
header[46] = (byte) 0x32; // -----
|
|
||||||
header[47] = (byte) 0x6b; // -----
|
|
||||||
|
|
||||||
header[48] = (byte) 0xdc; // Source Port
|
|
||||||
header[49] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[50] = (byte) 0x01; // Destination Port
|
|
||||||
header[51] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.TWO, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.TCP6, msg.protocolAndFamily());
|
|
||||||
assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", msg.sourceAddress());
|
|
||||||
assertEquals("1050:0:0:0:5:600:300c:326b", msg.destinationAddress());
|
|
||||||
assertEquals(56324, msg.sourcePort());
|
|
||||||
assertEquals(443, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testv2UnixDecode() {
|
|
||||||
byte[] header = new byte[232];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x31; // UNIX_STREAM
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0xd8; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0x2f; // Source Address
|
|
||||||
header[17] = (byte) 0x76; // -----
|
|
||||||
header[18] = (byte) 0x61; // -----
|
|
||||||
header[19] = (byte) 0x72; // -----
|
|
||||||
header[20] = (byte) 0x2f; // -----
|
|
||||||
header[21] = (byte) 0x72; // -----
|
|
||||||
header[22] = (byte) 0x75; // -----
|
|
||||||
header[23] = (byte) 0x6e; // -----
|
|
||||||
header[24] = (byte) 0x2f; // -----
|
|
||||||
header[25] = (byte) 0x73; // -----
|
|
||||||
header[26] = (byte) 0x72; // -----
|
|
||||||
header[27] = (byte) 0x63; // -----
|
|
||||||
header[28] = (byte) 0x2e; // -----
|
|
||||||
header[29] = (byte) 0x73; // -----
|
|
||||||
header[30] = (byte) 0x6f; // -----
|
|
||||||
header[31] = (byte) 0x63; // -----
|
|
||||||
header[32] = (byte) 0x6b; // -----
|
|
||||||
header[33] = (byte) 0x00; // -----
|
|
||||||
|
|
||||||
header[124] = (byte) 0x2f; // Destination Address
|
|
||||||
header[125] = (byte) 0x76; // -----
|
|
||||||
header[126] = (byte) 0x61; // -----
|
|
||||||
header[127] = (byte) 0x72; // -----
|
|
||||||
header[128] = (byte) 0x2f; // -----
|
|
||||||
header[129] = (byte) 0x72; // -----
|
|
||||||
header[130] = (byte) 0x75; // -----
|
|
||||||
header[131] = (byte) 0x6e; // -----
|
|
||||||
header[132] = (byte) 0x2f; // -----
|
|
||||||
header[133] = (byte) 0x64; // -----
|
|
||||||
header[134] = (byte) 0x65; // -----
|
|
||||||
header[135] = (byte) 0x73; // -----
|
|
||||||
header[136] = (byte) 0x74; // -----
|
|
||||||
header[137] = (byte) 0x2e; // -----
|
|
||||||
header[138] = (byte) 0x73; // -----
|
|
||||||
header[139] = (byte) 0x6f; // -----
|
|
||||||
header[140] = (byte) 0x63; // -----
|
|
||||||
header[141] = (byte) 0x6b; // -----
|
|
||||||
header[142] = (byte) 0x00; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.TWO, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.UNIX_STREAM, msg.protocolAndFamily());
|
|
||||||
assertEquals("/var/run/src.sock", msg.sourceAddress());
|
|
||||||
assertEquals("/var/run/dest.sock", msg.destinationAddress());
|
|
||||||
assertEquals(0, msg.sourcePort());
|
|
||||||
assertEquals(0, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testV2LocalProtocolDecode() {
|
|
||||||
byte[] header = new byte[28];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x20; // v2, cmd=LOCAL
|
|
||||||
header[13] = (byte) 0x00; // Unspecified transport protocol and address family
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0c; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.TWO, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.LOCAL, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.UNKNOWN, msg.protocolAndFamily());
|
|
||||||
assertNull(msg.sourceAddress());
|
|
||||||
assertNull(msg.destinationAddress());
|
|
||||||
assertEquals(0, msg.sourcePort());
|
|
||||||
assertEquals(0, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testV2UnknownProtocolDecode() {
|
|
||||||
byte[] header = new byte[28];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x00; // Unspecified transport protocol and address family
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0c; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.TWO, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.UNKNOWN, msg.protocolAndFamily());
|
|
||||||
assertNull(msg.sourceAddress());
|
|
||||||
assertNull(msg.destinationAddress());
|
|
||||||
assertEquals(0, msg.sourcePort());
|
|
||||||
assertEquals(0, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testV2WithTLV() {
|
|
||||||
ch = new EmbeddedChannel(new HAProxyProtocolDecoder(4));
|
|
||||||
|
|
||||||
byte[] header = new byte[236];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x31; // UNIX_STREAM
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0xdc; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0x2f; // Source Address
|
|
||||||
header[17] = (byte) 0x76; // -----
|
|
||||||
header[18] = (byte) 0x61; // -----
|
|
||||||
header[19] = (byte) 0x72; // -----
|
|
||||||
header[20] = (byte) 0x2f; // -----
|
|
||||||
header[21] = (byte) 0x72; // -----
|
|
||||||
header[22] = (byte) 0x75; // -----
|
|
||||||
header[23] = (byte) 0x6e; // -----
|
|
||||||
header[24] = (byte) 0x2f; // -----
|
|
||||||
header[25] = (byte) 0x73; // -----
|
|
||||||
header[26] = (byte) 0x72; // -----
|
|
||||||
header[27] = (byte) 0x63; // -----
|
|
||||||
header[28] = (byte) 0x2e; // -----
|
|
||||||
header[29] = (byte) 0x73; // -----
|
|
||||||
header[30] = (byte) 0x6f; // -----
|
|
||||||
header[31] = (byte) 0x63; // -----
|
|
||||||
header[32] = (byte) 0x6b; // -----
|
|
||||||
header[33] = (byte) 0x00; // -----
|
|
||||||
|
|
||||||
header[124] = (byte) 0x2f; // Destination Address
|
|
||||||
header[125] = (byte) 0x76; // -----
|
|
||||||
header[126] = (byte) 0x61; // -----
|
|
||||||
header[127] = (byte) 0x72; // -----
|
|
||||||
header[128] = (byte) 0x2f; // -----
|
|
||||||
header[129] = (byte) 0x72; // -----
|
|
||||||
header[130] = (byte) 0x75; // -----
|
|
||||||
header[131] = (byte) 0x6e; // -----
|
|
||||||
header[132] = (byte) 0x2f; // -----
|
|
||||||
header[133] = (byte) 0x64; // -----
|
|
||||||
header[134] = (byte) 0x65; // -----
|
|
||||||
header[135] = (byte) 0x73; // -----
|
|
||||||
header[136] = (byte) 0x74; // -----
|
|
||||||
header[137] = (byte) 0x2e; // -----
|
|
||||||
header[138] = (byte) 0x73; // -----
|
|
||||||
header[139] = (byte) 0x6f; // -----
|
|
||||||
header[140] = (byte) 0x63; // -----
|
|
||||||
header[141] = (byte) 0x6b; // -----
|
|
||||||
header[142] = (byte) 0x00; // -----
|
|
||||||
|
|
||||||
// ---- Additional data (TLV) ---- \\
|
|
||||||
|
|
||||||
header[232] = (byte) 0x01; // Type
|
|
||||||
header[233] = (byte) 0x00; // Remaining bytes
|
|
||||||
header[234] = (byte) 0x01; // -----
|
|
||||||
header[235] = (byte) 0x01; // Payload
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
Object msgObj = ch.readInbound();
|
|
||||||
assertEquals(startChannels - 1, ch.pipeline().names().size());
|
|
||||||
assertTrue(msgObj instanceof HAProxyProtocolMessage);
|
|
||||||
HAProxyProtocolMessage msg = (HAProxyProtocolMessage) msgObj;
|
|
||||||
assertEquals(HAProxyProtocolVersion.TWO, msg.version());
|
|
||||||
assertEquals(HAProxyProtocolCommand.PROXY, msg.command());
|
|
||||||
assertEquals(ProxiedProtocolAndFamily.UNIX_STREAM, msg.protocolAndFamily());
|
|
||||||
assertEquals("/var/run/src.sock", msg.sourceAddress());
|
|
||||||
assertEquals("/var/run/dest.sock", msg.destinationAddress());
|
|
||||||
assertEquals(0, msg.sourcePort());
|
|
||||||
assertEquals(0, msg.destinationPort());
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testV2InvalidProtocol() {
|
|
||||||
byte[] header = new byte[28];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x41; // Bogus transport protocol
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0c; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testV2MissingParams() {
|
|
||||||
byte[] header = new byte[26];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x11; // TCP over IPv4
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0a; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testV2InvalidCommand() {
|
|
||||||
byte[] header = new byte[28];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x22; // v2, Bogus command
|
|
||||||
header[13] = (byte) 0x11; // TCP over IPv4
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0c; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testV2InvalidVersion() {
|
|
||||||
byte[] header = new byte[28];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x31; // Bogus version, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x11; // TCP over IPv4
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0x0c; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = HAProxyProtocolException.class)
|
|
||||||
public void testV2HeaderTooLong() {
|
|
||||||
ch = new EmbeddedChannel(new HAProxyProtocolDecoder(0));
|
|
||||||
|
|
||||||
byte[] header = new byte[248];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
header[13] = (byte) 0x11; // TCP over IPv4
|
|
||||||
|
|
||||||
header[14] = (byte) 0x00; // Remaining Bytes
|
|
||||||
header[15] = (byte) 0xe8; // -----
|
|
||||||
|
|
||||||
header[16] = (byte) 0xc0; // Source Address
|
|
||||||
header[17] = (byte) 0xa8; // -----
|
|
||||||
header[18] = (byte) 0x00; // -----
|
|
||||||
header[19] = (byte) 0x01; // -----
|
|
||||||
|
|
||||||
header[20] = (byte) 0xc0; // Destination Address
|
|
||||||
header[21] = (byte) 0xa8; // -----
|
|
||||||
header[22] = (byte) 0x00; // -----
|
|
||||||
header[23] = (byte) 0x0b; // -----
|
|
||||||
|
|
||||||
header[24] = (byte) 0xdc; // Source Port
|
|
||||||
header[25] = (byte) 0x04; // -----
|
|
||||||
|
|
||||||
header[26] = (byte) 0x01; // Destination Port
|
|
||||||
header[27] = (byte) 0xbb; // -----
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testV2IncompleteHeader() {
|
|
||||||
byte[] header = new byte[13];
|
|
||||||
header[0] = (byte) 0x0D; // Binary Prefix
|
|
||||||
header[1] = (byte) 0x0A; // -----
|
|
||||||
header[2] = (byte) 0x0D; // -----
|
|
||||||
header[3] = (byte) 0x0A; // -----
|
|
||||||
header[4] = (byte) 0x00; // -----
|
|
||||||
header[5] = (byte) 0x0D; // -----
|
|
||||||
header[6] = (byte) 0x0A; // -----
|
|
||||||
header[7] = (byte) 0x51; // -----
|
|
||||||
header[8] = (byte) 0x55; // -----
|
|
||||||
header[9] = (byte) 0x49; // -----
|
|
||||||
header[10] = (byte) 0x54; // -----
|
|
||||||
header[11] = (byte) 0x0A; // -----
|
|
||||||
|
|
||||||
header[12] = (byte) 0x21; // v2, cmd=PROXY
|
|
||||||
|
|
||||||
int startChannels = ch.pipeline().names().size();
|
|
||||||
ch.writeInbound(copiedBuffer(header));
|
|
||||||
assertNull(ch.readInbound());
|
|
||||||
assertFalse(ch.finish());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user