1 /*
2 * Copyright 2016 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17 package io.netty.handler.codec.haproxy;
18
19 import io.netty.buffer.ByteBuf;
20 import io.netty.buffer.DefaultByteBufHolder;
21 import io.netty.util.internal.StringUtil;
22
23 import static io.netty.util.internal.ObjectUtil.*;
24
25 /**
26 * A Type-Length Value (TLV vector) that can be added to the PROXY protocol
27 * to include additional information like SSL information.
28 *
29 * @see HAProxySSLTLV
30 */
31 public class HAProxyTLV extends DefaultByteBufHolder {
32
33 private final Type type;
34 private final byte typeByteValue;
35
36 /**
37 * The size of this tlv in bytes.
38 * @return the number of bytes.
39 */
40 int totalNumBytes() {
41 return 3 + contentNumBytes(); // type(1) + length(2) + content
42 }
43
44 int contentNumBytes() {
45 return content().readableBytes();
46 }
47
48 /**
49 * The registered types a TLV can have regarding the PROXY protocol 1.5 spec
50 */
51 public enum Type {
52 PP2_TYPE_ALPN,
53 PP2_TYPE_AUTHORITY,
54 PP2_TYPE_SSL,
55 PP2_TYPE_SSL_VERSION,
56 PP2_TYPE_SSL_CN,
57 PP2_TYPE_NETNS,
58 /**
59 * A TLV type that is not officially defined in the spec. May be used for nonstandard TLVs
60 */
61 OTHER;
62
63 /**
64 * Returns the {@link Type} for a specific byte value as defined in the PROXY protocol 1.5 spec
65 * <p>
66 * If the byte value is not an official one, it will return {@link Type#OTHER}.
67 *
68 * @param byteValue the byte for a type
69 *
70 * @return the {@link Type} of a TLV
71 */
72 public static Type typeForByteValue(byte byteValue) {
73 switch (byteValue) {
74 case 0x01:
75 return PP2_TYPE_ALPN;
76 case 0x02:
77 return PP2_TYPE_AUTHORITY;
78 case 0x20:
79 return PP2_TYPE_SSL;
80 case 0x21:
81 return PP2_TYPE_SSL_VERSION;
82 case 0x22:
83 return PP2_TYPE_SSL_CN;
84 case 0x30:
85 return PP2_TYPE_NETNS;
86 default:
87 return OTHER;
88 }
89 }
90
91 /**
92 * Returns the byte value for the {@link Type} as defined in the PROXY protocol 1.5 spec.
93 *
94 * @param type the {@link Type}
95 *
96 * @return the byte value of the {@link Type}.
97 */
98 public static byte byteValueForType(Type type) {
99 switch (type) {
100 case PP2_TYPE_ALPN:
101 return 0x01;
102 case PP2_TYPE_AUTHORITY:
103 return 0x02;
104 case PP2_TYPE_SSL:
105 return 0x20;
106 case PP2_TYPE_SSL_VERSION:
107 return 0x21;
108 case PP2_TYPE_SSL_CN:
109 return 0x22;
110 case PP2_TYPE_NETNS:
111 return 0x30;
112 default:
113 throw new IllegalArgumentException("unknown type: " + type);
114 }
115 }
116 }
117
118 /**
119 * Creates a new HAProxyTLV
120 *
121 * @param typeByteValue the byteValue of the TLV. This is especially important if non-standard TLVs are used
122 * @param content the raw content of the TLV
123 */
124 public HAProxyTLV(byte typeByteValue, ByteBuf content) {
125 this(Type.typeForByteValue(typeByteValue), typeByteValue, content);
126 }
127
128 /**
129 * Creates a new HAProxyTLV
130 *
131 * @param type the {@link Type} of the TLV
132 * @param content the raw content of the TLV
133 */
134 public HAProxyTLV(Type type, ByteBuf content) {
135 this(type, Type.byteValueForType(type), content);
136 }
137
138 /**
139 * Creates a new HAProxyTLV
140 *
141 * @param type the {@link Type} of the TLV
142 * @param typeByteValue the byteValue of the TLV. This is especially important if non-standard TLVs are used
143 * @param content the raw content of the TLV
144 */
145 HAProxyTLV(final Type type, final byte typeByteValue, final ByteBuf content) {
146 super(content);
147 this.type = checkNotNull(type, "type");
148 this.typeByteValue = typeByteValue;
149 }
150
151 /**
152 * Returns the {@link Type} of this TLV
153 */
154 public Type type() {
155 return type;
156 }
157
158 /**
159 * Returns the type of the TLV as byte
160 */
161 public byte typeByteValue() {
162 return typeByteValue;
163 }
164
165 @Override
166 public HAProxyTLV copy() {
167 return replace(content().copy());
168 }
169
170 @Override
171 public HAProxyTLV duplicate() {
172 return replace(content().duplicate());
173 }
174
175 @Override
176 public HAProxyTLV retainedDuplicate() {
177 return replace(content().retainedDuplicate());
178 }
179
180 @Override
181 public HAProxyTLV replace(ByteBuf content) {
182 return new HAProxyTLV(type, typeByteValue, content);
183 }
184
185 @Override
186 public HAProxyTLV retain() {
187 super.retain();
188 return this;
189 }
190
191 @Override
192 public HAProxyTLV retain(int increment) {
193 super.retain(increment);
194 return this;
195 }
196
197 @Override
198 public HAProxyTLV touch() {
199 super.touch();
200 return this;
201 }
202
203 @Override
204 public HAProxyTLV touch(Object hint) {
205 super.touch(hint);
206 return this;
207 }
208
209 @Override
210 public String toString() {
211 return StringUtil.simpleClassName(this) +
212 "(type: " + type() +
213 ", typeByteValue: " + typeByteValue() +
214 ", content: " + contentToString() + ')';
215 }
216 }