Skip to content

Instantly share code, notes, and snippets.

@johnou
Last active May 10, 2020 14:51
Show Gist options
  • Save johnou/61129b6fae2f3df8517a417f86097db4 to your computer and use it in GitHub Desktop.
Save johnou/61129b6fae2f3df8517a417f86097db4 to your computer and use it in GitHub Desktop.
Index: codec-dns/src/main/java/io/netty/handler/codec/dns/DoHQueryEncoder.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- codec-dns/src/main/java/io/netty/handler/codec/dns/DoHQueryEncoder.java (revision 3f5a82f729f41b5e626e7cb3039c0b503dbcb05e)
+++ codec-dns/src/main/java/io/netty/handler/codec/dns/DoHQueryEncoder.java (date 1589121383858)
@@ -33,11 +33,11 @@
import java.util.List;
@UnstableApi
-public class DoHQueryEncoder extends MessageToMessageEncoder<DnsQuery> {
+public class DoHQueryEncoder extends MessageToMessageEncoder<DefaultDnsQuery> {
private final DnsQueryEncoder encoder;
- private final boolean HTTP2;
- private final boolean GET;
+ private final boolean http2;
+ private final boolean get;
private final URL url;
/**
@@ -51,14 +51,14 @@
}
/**
- * Creates a new encoder with {@linkplain DnsRecordEncoder#DEFAULT the default record encoder}, uses HTTP POST method
- * and specifies if we're using HTTP/2 (h2).
+ * Creates a new encoder with {@linkplain DnsRecordEncoder#DEFAULT the default record encoder}, uses HTTP POST
+ * method and specifies if we're using HTTP/2 (h2).
*
- * @param HTTP2 Use HTTP/2 (h2)
+ * @param http2 Use HTTP/2 (h2)
* @param url DoH Upstream Server
*/
- public DoHQueryEncoder(boolean HTTP2, URL url) {
- this(DnsRecordEncoder.DEFAULT, HTTP2, false, url);
+ public DoHQueryEncoder(boolean http2, URL url) {
+ this(DnsRecordEncoder.DEFAULT, http2, false, url);
}
/**
@@ -66,24 +66,24 @@
* {@code GET} and {@code url}
*
* @param recordEncoder DNS Record Encoder
- * @param HTTP2 Use HTTP/2 (h2)
- * @param GET Use HTTP GET method
+ * @param http2 Use HTTP/2 (h2)
+ * @param get Use HTTP GET method
* @param url DoH Upstream Server
*/
- public DoHQueryEncoder(DnsRecordEncoder recordEncoder, boolean HTTP2, boolean GET, URL url) {
+ public DoHQueryEncoder(DnsRecordEncoder recordEncoder, boolean http2, boolean get, URL url) {
this.encoder = new DnsQueryEncoder(recordEncoder);
- this.HTTP2 = HTTP2;
- this.GET = GET;
+ this.http2 = http2;
+ this.get = get;
this.url = url;
}
@Override
- protected void encode(ChannelHandlerContext ctx, DnsQuery msg, List<Object> out) throws Exception {
- ByteBuf byteBuf = ctx.alloc().buffer();
+ protected void encode(ChannelHandlerContext ctx, DefaultDnsQuery msg, List<Object> out) throws Exception {
+ ByteBuf byteBuf = ctx.alloc().buffer(); // TODO: is this freed?
encoder.encode(msg, byteBuf);
FullHttpRequest fullHttpRequest;
- if (GET) {
+ if (get) {
fullHttpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
url.getPath() + "?dns=" + Base64.encode(byteBuf).toString(Charset.forName("UTF-8")));
} else {
@@ -98,7 +98,7 @@
.add(HttpHeaderNames.ACCEPT, "application/dns-message");
// If we're using HTTP/2 (h2) then we'll add "x-http2-scheme" header
- if (HTTP2) {
+ if (http2) {
fullHttpRequest.headers().add(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text(),
HttpScheme.HTTPS.name());
}
Index: example/src/main/java/io/netty/example/dns/doh/ALPNHandler.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- example/src/main/java/io/netty/example/dns/doh/ALPNHandler.java (date 1589122224787)
+++ example/src/main/java/io/netty/example/dns/doh/ALPNHandler.java (date 1589122224787)
@@ -0,0 +1,81 @@
+package io.netty.example.dns.doh;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.dns.DoHQueryEncoder;
+import io.netty.handler.codec.dns.DoHResponseDecoder;
+import io.netty.handler.codec.http.HttpClientCodec;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http2.DefaultHttp2Connection;
+import io.netty.handler.codec.http2.DelegatingDecompressorFrameListener;
+import io.netty.handler.codec.http2.Http2Connection;
+import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandler;
+import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandlerBuilder;
+import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapter;
+import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapterBuilder;
+import io.netty.handler.ssl.ApplicationProtocolNames;
+import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
+import io.netty.util.concurrent.Promise;
+import io.netty.util.internal.ObjectUtil;
+
+import java.net.URL;
+
+final class ALPNHandler extends ApplicationProtocolNegotiationHandler {
+
+ private final URL url;
+ private final Promise<Void> promise;
+
+ ALPNHandler(URL url, Promise<Void> promise) {
+ super(ApplicationProtocolNames.HTTP_1_1);
+ this.url = url;
+ this.promise = ObjectUtil.checkNotNull(promise, "promise");
+ }
+
+ public Promise<Void> promise() {
+ return promise;
+ }
+
+ @Override
+ protected void configurePipeline(ChannelHandlerContext ctx, String protocol) {
+ if (protocol.equalsIgnoreCase(ApplicationProtocolNames.HTTP_2)) {
+ Http2Connection connection = new DefaultHttp2Connection(false);
+
+ InboundHttp2ToHttpAdapter listener = new InboundHttp2ToHttpAdapterBuilder(connection)
+ .propagateSettings(false)
+ .validateHttpHeaders(true)
+ .maxContentLength(1024 * 64)
+ .build();
+
+ HttpToHttp2ConnectionHandler http2Handler = new HttpToHttp2ConnectionHandlerBuilder()
+ .frameListener(new DelegatingDecompressorFrameListener(connection, listener))
+ .connection(connection)
+ .build();
+
+ ctx.pipeline().addLast(http2Handler,
+ new HttpObjectAggregator(1024 * 64, true),
+ new DoHQueryEncoder(true, url),
+ new DoHResponseDecoder(),
+ new Handler());
+ promise.setSuccess(null);
+ } else if (protocol.equalsIgnoreCase(ApplicationProtocolNames.HTTP_1_1)) {
+ ctx.pipeline().addLast(
+ new HttpClientCodec(),
+ new HttpObjectAggregator(1024 * 64, true),
+ new DoHQueryEncoder(url),
+ new DoHResponseDecoder(),
+ new Handler());
+ promise.setSuccess(null);
+ } else {
+ promise.setFailure(new IllegalArgumentException("Unsupported Protocol: " + protocol));
+ }
+ }
+
+ @Override
+ protected void handshakeFailure(ChannelHandlerContext ctx, Throwable cause) {
+ promise.setFailure(cause);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ promise.setFailure(cause);
+ }
+}
Index: example/src/main/java/io/netty/example/dns/doh/DoHClient.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- example/src/main/java/io/netty/example/dns/doh/DoHClient.java (revision 3f5a82f729f41b5e626e7cb3039c0b503dbcb05e)
+++ example/src/main/java/io/netty/example/dns/doh/DoHClient.java (date 1589122248788)
@@ -20,7 +20,6 @@
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
-
import io.netty.handler.codec.dns.DefaultDnsQuery;
import io.netty.handler.codec.dns.DefaultDnsQuestion;
import io.netty.handler.codec.dns.DnsOpCode;
@@ -31,8 +30,6 @@
import io.netty.handler.ssl.ApplicationProtocolNames;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
-import io.netty.handler.ssl.SslHandler;
-
import java.net.URL;
import java.util.concurrent.TimeUnit;
@@ -64,12 +61,10 @@
.channel(NioSocketChannel.class)
.handler(new Initializer(sslContext, url));
- final Channel ch = b.connect(url.getHost(), url.getDefaultPort()).sync().channel();
+ Channel ch = b.connect(url.getHost(), url.getDefaultPort()).sync().channel();
- // Wait for TLS Handshake to finish
- ch.pipeline().get(SslHandler.class).handshakeFuture().sync();
-
- Thread.sleep(500); // See https://github.com/netty/netty/pull/10258#discussion_r421823210
+ // Wait for application protocol negotiation to finish
+ ch.pipeline().get(ALPNHandler.class).promise().sync();
// RFC 8484 recommends ID 0 [https://tools.ietf.org/html/rfc8484#section-4.1]
DnsQuery query = new DefaultDnsQuery(0, DnsOpCode.QUERY);
Index: example/src/main/java/io/netty/example/dns/doh/Initializer.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- example/src/main/java/io/netty/example/dns/doh/Initializer.java (revision 3f5a82f729f41b5e626e7cb3039c0b503dbcb05e)
+++ example/src/main/java/io/netty/example/dns/doh/Initializer.java (date 1589122153928)
@@ -15,22 +15,8 @@
*/
package io.netty.example.dns.doh;
-import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
-import io.netty.handler.codec.dns.DoHQueryEncoder;
-import io.netty.handler.codec.dns.DoHResponseDecoder;
-import io.netty.handler.codec.http.HttpClientCodec;
-import io.netty.handler.codec.http.HttpObjectAggregator;
-import io.netty.handler.codec.http2.DefaultHttp2Connection;
-import io.netty.handler.codec.http2.DelegatingDecompressorFrameListener;
-import io.netty.handler.codec.http2.Http2Connection;
-import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandler;
-import io.netty.handler.codec.http2.HttpToHttp2ConnectionHandlerBuilder;
-import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapter;
-import io.netty.handler.codec.http2.InboundHttp2ToHttpAdapterBuilder;
-import io.netty.handler.ssl.ApplicationProtocolNames;
-import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
import io.netty.handler.ssl.SslContext;
import java.net.URL;
@@ -49,59 +35,7 @@
protected void initChannel(SocketChannel socketChannel) {
socketChannel.pipeline()
.addLast(sslCtx.newHandler(socketChannel.alloc(), url.getHost(), url.getDefaultPort()))
- .addLast(new ALPNHandler(url));
+ .addLast(new ALPNHandler(url, socketChannel.newPromise()));
}
-
- private static final class ALPNHandler extends ApplicationProtocolNegotiationHandler {
-
- private final URL url;
-
- private ALPNHandler(URL url) {
- super(ApplicationProtocolNames.HTTP_1_1);
- this.url = url;
- }
-
- @Override
- protected void configurePipeline(ChannelHandlerContext ctx, String protocol) {
- if (protocol.equalsIgnoreCase(ApplicationProtocolNames.HTTP_2)) {
- Http2Connection connection = new DefaultHttp2Connection(false);
-
- InboundHttp2ToHttpAdapter listener = new InboundHttp2ToHttpAdapterBuilder(connection)
- .propagateSettings(false)
- .validateHttpHeaders(true)
- .maxContentLength(1024 * 64)
- .build();
-
- HttpToHttp2ConnectionHandler http2Handler = new HttpToHttp2ConnectionHandlerBuilder()
- .frameListener(new DelegatingDecompressorFrameListener(connection, listener))
- .connection(connection)
- .build();
-
- ctx.pipeline().addLast(http2Handler,
- new HttpObjectAggregator(1024 * 64, true),
- new DoHQueryEncoder(true, url),
- new DoHResponseDecoder(),
- new Handler());
- } else if (protocol.equalsIgnoreCase(ApplicationProtocolNames.HTTP_1_1)) {
- ctx.pipeline().addLast(
- new HttpClientCodec(),
- new HttpObjectAggregator(1024 * 64, true),
- new DoHQueryEncoder(url),
- new DoHResponseDecoder(),
- new Handler());
- } else {
- throw new IllegalArgumentException("Unsupported Protocol: " + protocol);
- }
- }
- @Override
- protected void handshakeFailure(ChannelHandlerContext ctx, Throwable cause) {
- cause.printStackTrace();
- }
-
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
- cause.printStackTrace();
- }
- }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment