Skip to content

Commit 87477f4

Browse files
committed
Add support for HA Proxy Protocol TLV's
TLV's are supported in netty, but currently not accessible to vert.x users. Here the TLV's are exposed in `NetSocket#tlvs`
1 parent 1170f63 commit 87477f4

File tree

13 files changed

+163
-6
lines changed

13 files changed

+163
-6
lines changed

vertx-core/src/main/java/io/vertx/core/http/HttpConnection.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import io.vertx.core.Handler;
1717
import io.vertx.core.buffer.Buffer;
1818
import io.vertx.core.net.SocketAddress;
19+
import io.vertx.core.net.TLV;
1920

2021
import javax.net.ssl.SSLPeerUnverifiedException;
2122
import javax.net.ssl.SSLSession;
@@ -298,4 +299,10 @@ default List<Certificate> peerCertificates() throws SSLPeerUnverifiedException {
298299
*/
299300
String indicatedServerName();
300301

302+
/**
303+
* @return the type-length-values present in the TCP header, mainly used for HA Proxy Protocol v2
304+
*/
305+
@GenIgnore()
306+
List<TLV> tlvs();
307+
301308
}

vertx-core/src/main/java/io/vertx/core/http/impl/HttpNetSocket.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121
import io.vertx.core.net.NetSocket;
2222
import io.vertx.core.net.SSLOptions;
2323
import io.vertx.core.net.SocketAddress;
24+
import io.vertx.core.net.TLV;
2425
import io.vertx.core.streams.ReadStream;
2526
import io.vertx.core.streams.WriteStream;
2627

2728
import javax.net.ssl.SSLSession;
2829
import java.time.Duration;
30+
import java.util.List;
2931

3032
/**
3133
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
@@ -229,6 +231,11 @@ public SocketAddress localAddress(boolean real) {
229231
return stream.connection().localAddress(real);
230232
}
231233

234+
@Override
235+
public List<TLV> tlvs() {
236+
return stream.connection().tlvs();
237+
}
238+
232239
@Override
233240
public Future<Void> close() {
234241
return end();

vertx-core/src/main/java/io/vertx/core/http/impl/UnpooledHttpClientConnection.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
import io.vertx.core.internal.ContextInternal;
2222
import io.vertx.core.internal.PromiseInternal;
2323
import io.vertx.core.net.SocketAddress;
24+
import io.vertx.core.net.TLV;
2425

2526
import javax.net.ssl.SSLSession;
2627
import java.time.Duration;
2728
import java.util.ArrayDeque;
2829
import java.util.Deque;
29-
import java.util.concurrent.TimeUnit;
30+
import java.util.List;
3031

3132
/**
3233
* An un-pooled HTTP client connection that maintains a queue for pending requests that cannot be served
@@ -207,6 +208,11 @@ public String indicatedServerName() {
207208
return actual.indicatedServerName();
208209
}
209210

211+
@Override
212+
public List<TLV> tlvs() {
213+
return actual.tlvs();
214+
}
215+
210216
/**
211217
* Create an HTTP stream.
212218
*

vertx-core/src/main/java/io/vertx/core/http/impl/http3/Http3Connection.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import io.vertx.core.internal.quic.QuicConnectionInternal;
2727
import io.vertx.core.internal.quic.QuicStreamInternal;
2828
import io.vertx.core.net.SocketAddress;
29+
import io.vertx.core.net.TLV;
2930

3031
import javax.net.ssl.SSLSession;
3132
import java.time.Duration;
@@ -332,4 +333,9 @@ public HttpConnection pingHandler(@Nullable Handler<Buffer> handler) {
332333
public HttpConnection exceptionHandler(Handler<Throwable> handler) {
333334
return this;
334335
}
336+
337+
@Override
338+
public List<TLV> tlvs() {
339+
return connection.tlvs();
340+
}
335341
}

vertx-core/src/main/java/io/vertx/core/http/impl/tcp/Http2UpgradeClientConnection.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
import io.vertx.core.internal.logging.LoggerFactory;
3434
import io.vertx.core.net.HostAndPort;
3535
import io.vertx.core.net.SocketAddress;
36+
import io.vertx.core.net.TLV;
3637
import io.vertx.core.spi.metrics.ClientMetrics;
37-
import io.vertx.core.spi.metrics.HttpClientMetrics;
38+
3839

3940
import javax.net.ssl.SSLSession;
4041
import java.time.Duration;
42+
import java.util.List;
4143

4244
/**
4345
* A connection that attempts to perform a protocol upgrade to H2C. The connection might use HTTP/1 or H2C
@@ -901,6 +903,11 @@ public String indicatedServerName() {
901903
return current.indicatedServerName();
902904
}
903905

906+
@Override
907+
public List<TLV> tlvs() {
908+
return current.tlvs();
909+
}
910+
904911
@Override
905912
public String toString() {
906913
return getClass().getSimpleName() + "[current=" + current.getClass().getSimpleName() + "]";

vertx-core/src/main/java/io/vertx/core/net/NetSocket.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,5 +316,11 @@ default List<Certificate> peerCertificates() throws SSLPeerUnverifiedException {
316316
*/
317317
String applicationLayerProtocol();
318318

319+
/**
320+
* @return the type-length-values present in the TCP header, mainly used for HA Proxy Protocol v2
321+
*/
322+
@GenIgnore()
323+
List<TLV> tlvs();
324+
319325
}
320326

vertx-core/src/main/java/io/vertx/core/net/QuicConnection.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import javax.net.ssl.SSLSession;
2020
import java.time.Duration;
21+
import java.util.List;
2122

2223
/**
2324
* <p>A Quic connection between a client and a server, providing support for handling or creating Quic {@link QuicStream streams}</p>
@@ -176,4 +177,10 @@ default Future<Void> shutdown(Duration timeout) {
176177
*/
177178
SocketAddress localAddress();
178179

180+
/**
181+
* @return the type-length-values present in the TCP header, mainly used for HA Proxy Protocol v2
182+
*/
183+
@GenIgnore()
184+
List<TLV> tlvs();
185+
179186
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) 2011-2026 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
package io.vertx.core.net;
12+
13+
import io.vertx.core.buffer.Buffer;
14+
15+
public interface TLV {
16+
Buffer type();
17+
18+
Buffer value();
19+
}

vertx-core/src/main/java/io/vertx/core/net/impl/ConnectionBase.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
import io.vertx.core.internal.net.NetSocketInternal;
2828
import io.vertx.core.internal.net.SslHandshakeCompletionHandler;
2929
import io.vertx.core.net.SocketAddress;
30+
import io.vertx.core.net.TLV;
3031
import io.vertx.core.spi.metrics.NetworkMetrics;
3132
import io.vertx.core.spi.metrics.TransportMetrics;
3233

3334
import javax.net.ssl.SSLSession;
3435
import java.net.InetSocketAddress;
36+
import java.util.List;
3537

3638
/**
3739
* Abstract base class for connections managed by a vertx instance. This base implementation does not handle
@@ -53,6 +55,7 @@ public abstract class ConnectionBase {
5355
public static final VertxException CLOSED_EXCEPTION = NetSocketInternal.CLOSED_EXCEPTION;
5456
public static final AttributeKey<SocketAddress> REMOTE_ADDRESS_OVERRIDE = AttributeKey.valueOf("RemoteAddressOverride");
5557
public static final AttributeKey<SocketAddress> LOCAL_ADDRESS_OVERRIDE = AttributeKey.valueOf("LocalAddressOverride");
58+
public static final AttributeKey<List<TLV>> TLVS = AttributeKey.valueOf("TLVS");
5659
private static final Logger log = LoggerFactory.getLogger(ConnectionBase.class);
5760

5861
protected final VertxInternal vertx;
@@ -426,4 +429,8 @@ public SocketAddress localAddress(boolean real) {
426429
}
427430
}
428431

432+
public List<TLV> tlvs() {
433+
return channel.hasAttr(TLVS) ? channel.attr(TLVS).getAndSet(null) : null;
434+
}
435+
429436
}

vertx-core/src/main/java/io/vertx/core/net/impl/HAProxyMessageCompletionHandler.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
import io.vertx.core.internal.logging.Logger;
1212
import io.vertx.core.internal.logging.LoggerFactory;
1313
import io.vertx.core.net.SocketAddress;
14+
import io.vertx.core.net.TLV;
1415

1516
import java.io.IOException;
1617
import java.util.List;
18+
import java.util.Objects;
19+
import java.util.stream.Collectors;
1720

1821
public class HAProxyMessageCompletionHandler extends MessageToMessageDecoder<HAProxyMessage> {
1922
//Public because its used in tests
@@ -71,6 +74,11 @@ protected void decode(ChannelHandlerContext ctx, HAProxyMessage msg, List<Object
7174
ctx.channel().attr(ConnectionBase.LOCAL_ADDRESS_OVERRIDE)
7275
.set(createAddress(protocol, msg.destinationAddress(), msg.destinationPort()));
7376
}
77+
78+
if (msg.tlvs() != null) {
79+
ctx.channel().attr(ConnectionBase.TLVS)
80+
.set(createTLVs(msg.tlvs()));
81+
}
7482
}
7583
ctx.pipeline().remove(this);
7684
promise.setSuccess(ctx.channel());
@@ -103,4 +111,11 @@ private SocketAddress createAddress(HAProxyProxiedProtocol protocol, String sour
103111
throw new IllegalStateException("Should never happen");
104112
}
105113
}
114+
115+
private List<TLV> createTLVs(List<io.netty.handler.codec.haproxy.HAProxyTLV> haProxyTLVs) {
116+
return haProxyTLVs.stream()
117+
.filter(Objects::nonNull)
118+
.map(HAProxyTLV::from)
119+
.collect(Collectors.toList());
120+
}
106121
}

0 commit comments

Comments
 (0)