From c8847807d5bb71a1448674ef5e4fe33519c78f6a Mon Sep 17 00:00:00 2001 From: jrhee17 Date: Fri, 22 Nov 2019 01:30:26 +0900 Subject: [PATCH 01/10] try starting to add crypto frame --- .../netty/handler/codec/quic/QuicFrame.java | 27 +++++++++++++++++++ .../netty/handler/codec/quic/QuicRequest.java | 13 +++++---- .../handler/codec/quic/BasicQuicTest.java | 13 ++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 codec-quic/src/main/java/io/netty/handler/codec/quic/QuicFrame.java diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicFrame.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicFrame.java new file mode 100644 index 000000000000..e452f4153fe5 --- /dev/null +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicFrame.java @@ -0,0 +1,27 @@ +package io.netty.handler.codec.quic; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +public class QuicFrame { + public static final byte CRYPTO_TYPE = 0x06; + + private final byte type; + private final byte[] offset; + private final byte[] length; + private final byte[] data; + + public QuicFrame(byte type, byte[] offset, byte[] length, byte[] data) { + this.type = type; + this.offset = offset; + this.length = length; + this.data = data; + } + + public ByteBuf toByteBuf() { + return Unpooled.buffer().writeByte(type) + .writeBytes(offset) + .writeBytes(length) + .writeBytes(data); + } +} diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java index 8d08c9b3de0f..63b1e1c3767d 100644 --- a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java @@ -22,9 +22,11 @@ public class QuicRequest extends QuicMessage { private final int tokenLength; private final byte[] packetNumber; + private final QuicFrame quicFrame; + public QuicRequest(InetSocketAddress inetSocketAddress, int headerForm, int fixedBit, int longPacketType, int typeSpecificBits, int version, byte[] dcid, byte[] scid, int tokenLength, - byte[] packetNumber) { + byte[] packetNumber, QuicFrame quicFrame) { this.inetSocketAddress = inetSocketAddress; this.headerForm = headerForm; this.fixedBit = fixedBit; @@ -35,6 +37,7 @@ public QuicRequest(InetSocketAddress inetSocketAddress, int headerForm, int fixe this.scid = scid.clone(); this.tokenLength = tokenLength; this.packetNumber = packetNumber.clone(); + this.quicFrame = quicFrame; } public InetSocketAddress getInetSocketAddress() { @@ -43,8 +46,8 @@ public InetSocketAddress getInetSocketAddress() { @Override public ByteBuf getByteBuf() { - byte header = (byte) (((headerForm & 0x01) << 7) + ((fixedBit & 0x01) << 6) + ((longPacketType & 0x03) << 5) + (typeSpecificBits & 0x0f)); - System.out.println(header); + final byte header = (byte) (((headerForm & 0x01) << 7) + ((fixedBit & 0x01) << 6) + ((longPacketType & 0x03) << 5) + (typeSpecificBits & 0x0f)); + final ByteBuf frameByteBuf = quicFrame.toByteBuf(); return Unpooled.buffer() .writeByte(header) .writeInt(version) @@ -53,8 +56,8 @@ public ByteBuf getByteBuf() { .writeByte(scid.length - 1) .writeBytes(scid) .writeByte(tokenLength) - .writeBytes(variableLengthIntegerEncoding(packetNumber.length)) - .writeBytes(packetNumber); + .writeBytes(variableLengthIntegerEncoding(packetNumber.length + 1 + frameByteBuf.array().length)) + .writeBytes(packetNumber).writeByte(0x01).writeBytes(quicFrame.toByteBuf()); } static byte[] variableLengthIntegerEncoding(long length) { diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java index 9c3436a8baa2..e6c1c905f61f 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java @@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; +import io.netty.buffer.UnpooledByteBufAllocator; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -16,8 +17,11 @@ import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; import org.junit.Test; +import javax.net.ssl.SSLEngine; import java.net.InetSocketAddress; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; @@ -66,8 +70,15 @@ public void trySendInitialPacket() throws Exception { result.set(Unpooled.copiedBuffer(res)); latch.countDown(); }); + final SslContext sslContext = SslContextBuilder.forClient().protocols("TLSv1.3").build(); + final SSLEngine sslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); + sslEngine.beginHandshake(); + sslEngine.getSSLParameters(); + + final QuicFrame quicFrame = new QuicFrame((byte) 0x06, new byte[]{0}, new byte[] {0}, new byte[]{0}); client.writeAndFlush(new QuicRequest(remote, 1, 1, 0, 0, - 1, new byte[] {0}, new byte[] {0}, 0, new byte[] {0})).sync(); + 0x00000001, new byte[] {0}, new byte[] {0}, 0, new byte[] {0}, + quicFrame)).sync(); latch.await(); assertNotNull(result.get()); From b40c487f466bc35480f1aa177b7eb23b19472eea Mon Sep 17 00:00:00 2001 From: jrhee17 Date: Thu, 28 Nov 2019 01:40:48 +0900 Subject: [PATCH 02/10] start implementing tls test code --- .../handler/codec/quic/BasicQuicTest.java | 4 --- .../handler/codec/quic/BasicSslTest.java | 31 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java index e6c1c905f61f..2e9f5c5ffec2 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java @@ -70,10 +70,6 @@ public void trySendInitialPacket() throws Exception { result.set(Unpooled.copiedBuffer(res)); latch.countDown(); }); - final SslContext sslContext = SslContextBuilder.forClient().protocols("TLSv1.3").build(); - final SSLEngine sslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); - sslEngine.beginHandshake(); - sslEngine.getSSLParameters(); final QuicFrame quicFrame = new QuicFrame((byte) 0x06, new byte[]{0}, new byte[] {0}, new byte[]{0}); client.writeAndFlush(new QuicRequest(remote, 1, 1, 0, 0, diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java new file mode 100644 index 000000000000..b3cf7ea56723 --- /dev/null +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java @@ -0,0 +1,31 @@ +package io.netty.handler.codec.quic; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import io.netty.buffer.UnpooledByteBufAllocator; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import org.junit.Test; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.Status; +import java.nio.ByteBuffer; + +public class BasicSslTest { + @Test + public void sandboxSslTest() throws Exception { + final SslContext sslContext = SslContextBuilder.forClient().protocols("TLSv1.2").build(); + final SSLEngine sslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); + + final int appBufferSize = sslEngine.getSession().getApplicationBufferSize(); + ByteBuffer src = ByteBuffer.allocate(10); + ByteBuffer dst = ByteBuffer.allocate(appBufferSize * 2); + SSLEngineResult result = sslEngine.wrap(src, dst); + + System.out.println(ByteBufUtil.prettyHexDump(Unpooled.copiedBuffer(dst)));; + System.out.println(dst.remaining()); + System.out.println(result); + } +} From c85f2791fb742c063942b12175fb3f6e4f527a61 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 3 Dec 2019 01:19:15 +0900 Subject: [PATCH 03/10] checkpoint --- .../handler/codec/quic/BasicSslTest.java | 170 ++++++++++++++++-- 1 file changed, 160 insertions(+), 10 deletions(-) diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java index b3cf7ea56723..3d7332ab1381 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java @@ -1,31 +1,181 @@ package io.netty.handler.codec.quic; -import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.buffer.UnpooledByteBufAllocator; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.SelfSignedCertificate; import org.junit.Test; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLException; import java.nio.ByteBuffer; +import java.security.cert.CertificateException; public class BasicSslTest { + + private volatile SSLEngine clientSslEngine; + private volatile SSLEngine serverSslEngine; + + private final SelfSignedCertificate ssc = new SelfSignedCertificate(); + + public BasicSslTest() throws CertificateException { + } + + private SSLEngine clientSslEngine() throws SSLException { + if (clientSslEngine == null) { + synchronized (this) { + if (clientSslEngine == null) { + final SslContext sslContext = SslContextBuilder.forClient().trustManager(ssc.cert()).protocols( + "TLSv1.2").build(); + clientSslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); + } + } + } + return clientSslEngine; + } + + private SSLEngine serverSslEngine() throws SSLException, CertificateException { + if (serverSslEngine == null) { + synchronized (this) { + if (serverSslEngine == null) { + + final SslContext sslContext = SslContextBuilder.forServer( + ssc.certificate(), ssc.privateKey()).protocols("TLSv1", "TLSv1.1", "TLSv1.2").build(); + serverSslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); + } + } + } + return serverSslEngine; + } + @Test public void sandboxSslTest() throws Exception { - final SslContext sslContext = SslContextBuilder.forClient().protocols("TLSv1.2").build(); - final SSLEngine sslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); - final int appBufferSize = sslEngine.getSession().getApplicationBufferSize(); - ByteBuffer src = ByteBuffer.allocate(10); - ByteBuffer dst = ByteBuffer.allocate(appBufferSize * 2); - SSLEngineResult result = sslEngine.wrap(src, dst); + assert clientSslEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING; + + clientSslEngine().beginHandshake(); + + assert clientSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_WRAP; + + final int packetBufferSize = clientSslEngine().getSession().getPacketBufferSize(); + ByteBuffer src = ByteBuffer.allocate(0); + ByteBuffer dst = ByteBuffer.allocate(packetBufferSize); + SSLEngineResult result = clientSslEngine().wrap(src, dst); + + assert result.getStatus() == Status.OK; + assert result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; + + assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING; + + serverSslEngine().beginHandshake(); + + assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; + + dst.flip(); + ByteBuffer dst2 = ByteBuffer.allocate(serverSslEngine().getSession().getApplicationBufferSize()); + SSLEngineResult serverResult1 = serverSslEngine().unwrap(dst, dst2); + + assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_TASK; + assert serverResult1.getStatus() == Status.OK; + + Runnable task; + while ((task = serverSslEngine().getDelegatedTask()) != null) { + task.run(); + } + + assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_WRAP; + + ByteBuffer dst3 = ByteBuffer.allocate(serverSslEngine().getSession().getPacketBufferSize()); + SSLEngineResult serverResult2 = serverSslEngine().wrap(ByteBuffer.allocate(0), dst3); + + assert serverResult2.getStatus() == Status.OK; + + ByteBuffer dst4 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + dst3.flip(); + SSLEngineResult clientResult2 = clientSslEngine().unwrap(dst3, dst4); + + assert clientResult2.getHandshakeStatus() == HandshakeStatus.NEED_TASK; + assert clientResult2.getStatus() == Status.OK; + + while ((task = clientSslEngine().getDelegatedTask()) != null) { + task.run(); + } + + assert clientSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_WRAP; + + ByteBuffer dst5 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + SSLEngineResult clientResult3 = clientSslEngine().wrap(ByteBuffer.allocate(0), dst5); + + assert clientResult3.getStatus() == Status.OK; + assert clientResult3.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; + + ByteBuffer dst6 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + SSLEngineResult clientResult4 = clientSslEngine().wrap(ByteBuffer.allocate(0), dst6); + + assert clientResult4.getStatus() == Status.OK; + assert clientResult4.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; + + ByteBuffer dst7 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + SSLEngineResult clientResult5 = clientSslEngine().wrap(ByteBuffer.allocate(0), dst7); + + assert clientResult5.getStatus() == Status.OK; + assert clientResult5.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; + + ByteBuffer dst8 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + dst5.flip(); + SSLEngineResult serverResult3 = serverSslEngine().unwrap(dst5, dst8); + + assert serverResult3.getStatus() == Status.OK; + assert serverResult3.getHandshakeStatus() == HandshakeStatus.NEED_TASK; + + while ((task = serverSslEngine().getDelegatedTask()) != null) { + task.run(); + } + + assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; + + ByteBuffer dst9 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + dst6.flip(); + SSLEngineResult serverResult4 = serverSslEngine().unwrap(dst6, dst9); + + assert serverResult4.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; + assert serverResult4.getStatus() == Status.OK; + + ByteBuffer dst10 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + dst7.flip(); + SSLEngineResult serverResult5 = serverSslEngine().unwrap(dst7, dst10); + + assert serverResult5.getStatus() == Status.OK; + + ByteBuffer dst11 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + SSLEngineResult serverResult6 = serverSslEngine().wrap(ByteBuffer.allocate(0), dst11); + + assert serverResult6.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; + assert serverResult6.getStatus() == Status.OK; + + ByteBuffer dst12 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + SSLEngineResult serverResult7 = serverSslEngine().wrap(ByteBuffer.allocate(0), dst12); + + assert serverResult7.getHandshakeStatus() == HandshakeStatus.FINISHED; + assert serverResult7.getStatus() == Status.OK; + + ByteBuffer dst13 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + dst11.flip(); + SSLEngineResult clientResult6 = clientSslEngine().unwrap(dst11, dst13); + + assert clientResult6.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; + assert clientResult6.getStatus() == Status.OK; + + ByteBuffer dst14 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + dst12.flip(); + SSLEngineResult clientResult7 = clientSslEngine().unwrap(dst12, dst14); - System.out.println(ByteBufUtil.prettyHexDump(Unpooled.copiedBuffer(dst)));; - System.out.println(dst.remaining()); - System.out.println(result); + assert clientResult7.getStatus() == Status.OK; + assert clientResult7.getHandshakeStatus() == HandshakeStatus.FINISHED; } } From 1287605acbdd2b380fc11d51626083ce8101b718 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 3 Dec 2019 02:13:47 +0900 Subject: [PATCH 04/10] try implementing ssl using jdk api --- .../handler/codec/quic/BasicSslTest.java | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java index 3d7332ab1381..126db5ab59de 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicSslTest.java @@ -1,7 +1,5 @@ package io.netty.handler.codec.quic; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; import io.netty.buffer.UnpooledByteBufAllocator; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; @@ -21,7 +19,8 @@ public class BasicSslTest { private volatile SSLEngine clientSslEngine; private volatile SSLEngine serverSslEngine; - private final SelfSignedCertificate ssc = new SelfSignedCertificate(); + private final SelfSignedCertificate cert = new SelfSignedCertificate(); + private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); public BasicSslTest() throws CertificateException { } @@ -30,7 +29,7 @@ private SSLEngine clientSslEngine() throws SSLException { if (clientSslEngine == null) { synchronized (this) { if (clientSslEngine == null) { - final SslContext sslContext = SslContextBuilder.forClient().trustManager(ssc.cert()).protocols( + final SslContext sslContext = SslContextBuilder.forClient().trustManager(cert.cert()).protocols( "TLSv1.2").build(); clientSslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); } @@ -45,7 +44,7 @@ private SSLEngine serverSslEngine() throws SSLException, CertificateException { if (serverSslEngine == null) { final SslContext sslContext = SslContextBuilder.forServer( - ssc.certificate(), ssc.privateKey()).protocols("TLSv1", "TLSv1.1", "TLSv1.2").build(); + cert.certificate(), cert.privateKey()).protocols("TLSv1", "TLSv1.1", "TLSv1.2").build(); serverSslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT); } } @@ -56,16 +55,22 @@ private SSLEngine serverSslEngine() throws SSLException, CertificateException { @Test public void sandboxSslTest() throws Exception { + ByteBuffer clientPacketBuf = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); + ByteBuffer serverPacketBuf = ByteBuffer.allocate(serverSslEngine().getSession().getPacketBufferSize()); + + ByteBuffer serverAppBuf = ByteBuffer.allocate( + serverSslEngine().getSession().getApplicationBufferSize()); + ByteBuffer clientAppBuf = ByteBuffer.allocate( + clientSslEngine().getSession().getApplicationBufferSize()); + + // Start client side handshaking assert clientSslEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING; clientSslEngine().beginHandshake(); assert clientSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_WRAP; - final int packetBufferSize = clientSslEngine().getSession().getPacketBufferSize(); - ByteBuffer src = ByteBuffer.allocate(0); - ByteBuffer dst = ByteBuffer.allocate(packetBufferSize); - SSLEngineResult result = clientSslEngine().wrap(src, dst); + SSLEngineResult result = clientSslEngine().wrap(EMPTY_BUFFER, clientPacketBuf); assert result.getStatus() == Status.OK; assert result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; @@ -76,9 +81,9 @@ public void sandboxSslTest() throws Exception { assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; - dst.flip(); - ByteBuffer dst2 = ByteBuffer.allocate(serverSslEngine().getSession().getApplicationBufferSize()); - SSLEngineResult serverResult1 = serverSslEngine().unwrap(dst, dst2); + clientPacketBuf.flip(); + SSLEngineResult serverResult1 = serverSslEngine().unwrap(clientPacketBuf, serverAppBuf); + clientPacketBuf.compact(); assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_TASK; assert serverResult1.getStatus() == Status.OK; @@ -90,14 +95,13 @@ public void sandboxSslTest() throws Exception { assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_WRAP; - ByteBuffer dst3 = ByteBuffer.allocate(serverSslEngine().getSession().getPacketBufferSize()); - SSLEngineResult serverResult2 = serverSslEngine().wrap(ByteBuffer.allocate(0), dst3); + SSLEngineResult serverResult2 = serverSslEngine().wrap(EMPTY_BUFFER, serverPacketBuf); assert serverResult2.getStatus() == Status.OK; - ByteBuffer dst4 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - dst3.flip(); - SSLEngineResult clientResult2 = clientSslEngine().unwrap(dst3, dst4); + serverPacketBuf.flip(); + SSLEngineResult clientResult2 = clientSslEngine().unwrap(serverPacketBuf, clientAppBuf); + serverPacketBuf.compact(); assert clientResult2.getHandshakeStatus() == HandshakeStatus.NEED_TASK; assert clientResult2.getStatus() == Status.OK; @@ -108,27 +112,14 @@ public void sandboxSslTest() throws Exception { assert clientSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_WRAP; - ByteBuffer dst5 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - SSLEngineResult clientResult3 = clientSslEngine().wrap(ByteBuffer.allocate(0), dst5); + SSLEngineResult clientResult3 = clientSslEngine().wrap(EMPTY_BUFFER, clientPacketBuf); assert clientResult3.getStatus() == Status.OK; assert clientResult3.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; - ByteBuffer dst6 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - SSLEngineResult clientResult4 = clientSslEngine().wrap(ByteBuffer.allocate(0), dst6); - - assert clientResult4.getStatus() == Status.OK; - assert clientResult4.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; - - ByteBuffer dst7 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - SSLEngineResult clientResult5 = clientSslEngine().wrap(ByteBuffer.allocate(0), dst7); - - assert clientResult5.getStatus() == Status.OK; - assert clientResult5.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; - - ByteBuffer dst8 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - dst5.flip(); - SSLEngineResult serverResult3 = serverSslEngine().unwrap(dst5, dst8); + clientPacketBuf.flip(); + SSLEngineResult serverResult3 = serverSslEngine().unwrap(clientPacketBuf, serverAppBuf); + clientPacketBuf.compact(); assert serverResult3.getStatus() == Status.OK; assert serverResult3.getHandshakeStatus() == HandshakeStatus.NEED_TASK; @@ -139,41 +130,50 @@ public void sandboxSslTest() throws Exception { assert serverSslEngine().getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; - ByteBuffer dst9 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - dst6.flip(); - SSLEngineResult serverResult4 = serverSslEngine().unwrap(dst6, dst9); + SSLEngineResult clientResult4 = clientSslEngine().wrap(EMPTY_BUFFER, clientPacketBuf); + + assert clientResult4.getStatus() == Status.OK; + assert clientResult4.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; + + clientPacketBuf.flip(); + SSLEngineResult serverResult4 = serverSslEngine().unwrap(clientPacketBuf, serverAppBuf); + clientPacketBuf.compact(); assert serverResult4.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; assert serverResult4.getStatus() == Status.OK; - ByteBuffer dst10 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - dst7.flip(); - SSLEngineResult serverResult5 = serverSslEngine().unwrap(dst7, dst10); + SSLEngineResult clientResult5 = clientSslEngine().wrap(EMPTY_BUFFER, clientPacketBuf); + + assert clientResult5.getStatus() == Status.OK; + assert clientResult5.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; + + clientPacketBuf.flip(); + SSLEngineResult serverResult5 = serverSslEngine().unwrap(clientPacketBuf, serverAppBuf); + clientPacketBuf.compact(); assert serverResult5.getStatus() == Status.OK; + assert serverResult5.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; - ByteBuffer dst11 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - SSLEngineResult serverResult6 = serverSslEngine().wrap(ByteBuffer.allocate(0), dst11); + SSLEngineResult serverResult6 = serverSslEngine().wrap(EMPTY_BUFFER, serverPacketBuf); assert serverResult6.getHandshakeStatus() == HandshakeStatus.NEED_WRAP; assert serverResult6.getStatus() == Status.OK; - ByteBuffer dst12 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - SSLEngineResult serverResult7 = serverSslEngine().wrap(ByteBuffer.allocate(0), dst12); - - assert serverResult7.getHandshakeStatus() == HandshakeStatus.FINISHED; - assert serverResult7.getStatus() == Status.OK; - - ByteBuffer dst13 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - dst11.flip(); - SSLEngineResult clientResult6 = clientSslEngine().unwrap(dst11, dst13); + serverPacketBuf.flip(); + SSLEngineResult clientResult6 = clientSslEngine().unwrap(serverPacketBuf, clientAppBuf); + serverPacketBuf.compact(); assert clientResult6.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP; assert clientResult6.getStatus() == Status.OK; - ByteBuffer dst14 = ByteBuffer.allocate(clientSslEngine().getSession().getPacketBufferSize()); - dst12.flip(); - SSLEngineResult clientResult7 = clientSslEngine().unwrap(dst12, dst14); + SSLEngineResult serverResult7 = serverSslEngine().wrap(EMPTY_BUFFER, serverPacketBuf); + + assert serverResult7.getHandshakeStatus() == HandshakeStatus.FINISHED; + assert serverResult7.getStatus() == Status.OK; + + serverPacketBuf.flip(); + SSLEngineResult clientResult7 = clientSslEngine().unwrap(serverPacketBuf, clientAppBuf); + serverPacketBuf.compact(); assert clientResult7.getStatus() == Status.OK; assert clientResult7.getHandshakeStatus() == HandshakeStatus.FINISHED; From ba6bee2476e7988db2d3b288d030d452b90cbc67 Mon Sep 17 00:00:00 2001 From: jrhee17 Date: Fri, 6 Dec 2019 01:56:25 +0900 Subject: [PATCH 05/10] start with a hard coded version of client hello --- .../handler/codec/quic/BasicQuicTest.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java index 2e9f5c5ffec2..90cc4dc5ace6 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/BasicQuicTest.java @@ -4,7 +4,6 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; -import io.netty.buffer.UnpooledByteBufAllocator; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; @@ -17,11 +16,8 @@ import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.handler.logging.LoggingHandler; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; import org.junit.Test; -import javax.net.ssl.SSLEngine; import java.net.InetSocketAddress; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; @@ -34,7 +30,7 @@ public class BasicQuicTest { private static final String ECHO_MESSAGE = "hai:)"; private static final String CHROMIUM_ENDPOINT = "https://quic.rocks:4433/"; - + private static final String SAMPLE_INITIAL_HEXDUMP_PACKET = "cfff00001810b57f88e894e16fda41d0f29f49677f751477bc1a6f2950e4a601dd16df156bb93535e08711004482f6fff9222619c5ff07a85338139476ccda979adbc2f04e90fbbf8f8266af3005306fbba8b0f7dc6b89e0a4485ccfeaa8fe2d6c59bc0e1b376f6f02c5bc8ac90404bd7d2b3accd2c11e519092042957e9863a9ce927b7176f7536c46489ca7710b6e485b53edc43f44f5108f6a52d783a64d24857ba2ce24b5eeafe39cf02e8547fdb814e67d5c3c60045ce6c6a4f0113c895502c63f5c52c4c6dea34c91cc0691f6764507fc0f63af13a59728b063ada930234ba9b05f5f7d4add36b15028a2d892a55c798e96bbdc3bb91490cde96c9f37d336baa287584cc93101d5284ac340bbd29c3548c098532446e0bb95508fb878c33bc21a34273d15552a0fd450da2748700550ea33c187d0fd7bb0a94b57eb0803be430483118e8fe98fbeb8608436d8f39abe30c28fba360fc4675e401d64c1bd87bdfb647422a05432d7aaeeb600c85bbfbb99bda07deb2a5faf17f8c1b5de461fb6c41faa20338e54531b3080893af30c8aab269fef41051772df2b0a05ba393505b29c8b9edfd3085f359a64c2c8749aeb82e1ac7d0f3234af47b7ec9a51dbb81debbfc72490aad40c5377298d8cf0b21bf8f8750dfe3b45833f6a425d9cd8daaeb1aac1c44e69f198b5a9015364177bcba7f5022b6fdaf123de110360b0dd619a37dc96cbe2809df1e481a7e3b500911cb49c1bfe8dca4c6230ab816f187875a4c70198534f4e3e77ec76341f00135d3d7b701f3a1f2e6743b45d3af9a00fe4938fba2ab30cb3d3c67d0a237ab0be45e1229b72280bdec7e61c01da2329967a21ced88adc79e73818eb8aa583591c85f34dfe1231b70c5769cd8945bd642b607453c853b2061fd259b57e09743e54d6cd7b6344a1e9a817b94e2272f797a0a171ac14de318986bdf723eab648f3deeb4e18211f37e79a014e7b39ff07bf84b353936de53868f70a7a3d1be70186e741eeff84461afe9905a85ea18f0ec3586f332f3ef2db99921be70f2b89450b7e45b2ae381d4ef4e32abbfd5c11736da4c871bc7eacab8a5b7238925fd3cb8acd824de004b55bdc78bc6f518666772cd945444101d27f5141926246d7e8d95009ed2763d0bf88411f5eace577850d04d15e172116fc1fcd7d246d0a837627b6e7a610365e343d7544dd46c799daf74c05ed9c1a6b71c3598b9b4f7461f45cb88c6a6005269b9f8b1b3aefad2e7c3a12831d428337699fc414bde0320dc334ba06ac88c3522f8636b50c4bc15a1d088757c62882d5495b06d4d83fee1ecff34ab20f5e7003aae70a962d7ded730fc5ee75cb2fb8601429bec3211a70c194ba903bb38e1f182612dedfad96702c6cf55046fe04f89a3534d4006f288ffbd38d89dbbbd9d37ab5c188ee45264410f9fea51d393710b1ae834a80d91edda4aa63f60bfa582bb4451408f30b1e4dbef075b6f6554b7ac31ed7520158ee2fe7bff6a7038762826c6c40553f5b567f06fc75b3f387e9ddf3f1486348158868de7166679442cdee500ef61fb76dcf80d5a7c819831276e86d8736cdb21ee2aa22e0ca55c83bafc56e74be1ad935150653f6c34dd39bb67ab2357a873f0428df56d1c6f9a583c5feac8cfa71da32b8527d0de7baf725959b862b915bd091a7ea9ab6e4e72"; @Test public void testSimpleEcho() throws Throwable { @@ -56,8 +52,8 @@ public void testSimpleEcho() throws Throwable { assertEquals(ECHO_MESSAGE, result.get()); - serverChannel.closeFuture().await(); - clientChannel.closeFuture().await(); + serverChannel.close().await(); + clientChannel.close().await(); } @Test @@ -71,10 +67,12 @@ public void trySendInitialPacket() throws Exception { latch.countDown(); }); - final QuicFrame quicFrame = new QuicFrame((byte) 0x06, new byte[]{0}, new byte[] {0}, new byte[]{0}); - client.writeAndFlush(new QuicRequest(remote, 1, 1, 0, 0, - 0x00000001, new byte[] {0}, new byte[] {0}, 0, new byte[] {0}, - quicFrame)).sync(); +// final QuicFrame quicFrame = new QuicFrame((byte) 0x06, new byte[]{0}, new byte[] {0}, new byte[]{0}); +// client.writeAndFlush(new QuicRequest(remote, 1, 1, 0, 0, +// 0x00000001, new byte[] {0}, new byte[] {0}, 0, new byte[] {0}, +// quicFrame)).sync(); + client.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(ByteBufUtil.decodeHexDump( + SAMPLE_INITIAL_HEXDUMP_PACKET)), remote)).sync(); latch.await(); assertNotNull(result.get()); From 038cde742323edd02dbb4d39e284924b659dd81b Mon Sep 17 00:00:00 2001 From: jrhee17 Date: Tue, 10 Dec 2019 00:41:39 +0900 Subject: [PATCH 06/10] add skeleton for implementing quicrequestdecoder --- .../codec/quic/QuicRequestDecoder.java | 15 ++++++++++ .../codec/quic/QuicRequestDecoderTest.java | 30 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java create mode 100644 codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java new file mode 100644 index 000000000000..e9c4eadb47c7 --- /dev/null +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java @@ -0,0 +1,15 @@ +package io.netty.handler.codec.quic; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.DatagramPacket; +import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.util.ReferenceCountUtil; + +import java.util.List; + +public class QuicRequestDecoder extends MessageToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List out) throws Exception { + out.add(new QuicMessage(ReferenceCountUtil.retain(msg.content()))); + } +} diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java new file mode 100644 index 000000000000..03dae65a0055 --- /dev/null +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java @@ -0,0 +1,30 @@ +package io.netty.handler.codec.quic; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.channel.local.LocalAddress; +import io.netty.channel.socket.DatagramPacket; +import org.junit.Test; + +import java.net.InetSocketAddress; + +import static org.junit.Assert.*; + +public class QuicRequestDecoderTest { + private static final String SAMPLE_INITIAL_HEXDUMP_PACKET = "cfff00001810b57f88e894e16fda41d0f29f49677f751477bc1a6f2950e4a601dd16df156bb93535e08711004482f6fff9222619c5ff07a85338139476ccda979adbc2f04e90fbbf8f8266af3005306fbba8b0f7dc6b89e0a4485ccfeaa8fe2d6c59bc0e1b376f6f02c5bc8ac90404bd7d2b3accd2c11e519092042957e9863a9ce927b7176f7536c46489ca7710b6e485b53edc43f44f5108f6a52d783a64d24857ba2ce24b5eeafe39cf02e8547fdb814e67d5c3c60045ce6c6a4f0113c895502c63f5c52c4c6dea34c91cc0691f6764507fc0f63af13a59728b063ada930234ba9b05f5f7d4add36b15028a2d892a55c798e96bbdc3bb91490cde96c9f37d336baa287584cc93101d5284ac340bbd29c3548c098532446e0bb95508fb878c33bc21a34273d15552a0fd450da2748700550ea33c187d0fd7bb0a94b57eb0803be430483118e8fe98fbeb8608436d8f39abe30c28fba360fc4675e401d64c1bd87bdfb647422a05432d7aaeeb600c85bbfbb99bda07deb2a5faf17f8c1b5de461fb6c41faa20338e54531b3080893af30c8aab269fef41051772df2b0a05ba393505b29c8b9edfd3085f359a64c2c8749aeb82e1ac7d0f3234af47b7ec9a51dbb81debbfc72490aad40c5377298d8cf0b21bf8f8750dfe3b45833f6a425d9cd8daaeb1aac1c44e69f198b5a9015364177bcba7f5022b6fdaf123de110360b0dd619a37dc96cbe2809df1e481a7e3b500911cb49c1bfe8dca4c6230ab816f187875a4c70198534f4e3e77ec76341f00135d3d7b701f3a1f2e6743b45d3af9a00fe4938fba2ab30cb3d3c67d0a237ab0be45e1229b72280bdec7e61c01da2329967a21ced88adc79e73818eb8aa583591c85f34dfe1231b70c5769cd8945bd642b607453c853b2061fd259b57e09743e54d6cd7b6344a1e9a817b94e2272f797a0a171ac14de318986bdf723eab648f3deeb4e18211f37e79a014e7b39ff07bf84b353936de53868f70a7a3d1be70186e741eeff84461afe9905a85ea18f0ec3586f332f3ef2db99921be70f2b89450b7e45b2ae381d4ef4e32abbfd5c11736da4c871bc7eacab8a5b7238925fd3cb8acd824de004b55bdc78bc6f518666772cd945444101d27f5141926246d7e8d95009ed2763d0bf88411f5eace577850d04d15e172116fc1fcd7d246d0a837627b6e7a610365e343d7544dd46c799daf74c05ed9c1a6b71c3598b9b4f7461f45cb88c6a6005269b9f8b1b3aefad2e7c3a12831d428337699fc414bde0320dc334ba06ac88c3522f8636b50c4bc15a1d088757c62882d5495b06d4d83fee1ecff34ab20f5e7003aae70a962d7ded730fc5ee75cb2fb8601429bec3211a70c194ba903bb38e1f182612dedfad96702c6cf55046fe04f89a3534d4006f288ffbd38d89dbbbd9d37ab5c188ee45264410f9fea51d393710b1ae834a80d91edda4aa63f60bfa582bb4451408f30b1e4dbef075b6f6554b7ac31ed7520158ee2fe7bff6a7038762826c6c40553f5b567f06fc75b3f387e9ddf3f1486348158868de7166679442cdee500ef61fb76dcf80d5a7c819831276e86d8736cdb21ee2aa22e0ca55c83bafc56e74be1ad935150653f6c34dd39bb67ab2357a873f0428df56d1c6f9a583c5feac8cfa71da32b8527d0de7baf725959b862b915bd091a7ea9ab6e4e72"; + + @Test + public void testEncoding() { + final byte[] bytes = ByteBufUtil.decodeHexDump(SAMPLE_INITIAL_HEXDUMP_PACKET); + final ByteBuf byteBuf = Unpooled.copiedBuffer(bytes); + final InetSocketAddress remote = new InetSocketAddress(0); + final DatagramPacket datagramPacket = new DatagramPacket(byteBuf, remote); + + final EmbeddedChannel channel = new EmbeddedChannel(new QuicRequestDecoder()); + channel.writeInbound(datagramPacket); + + assertTrue(channel.readInbound() instanceof QuicMessage); + } +} From 2862b2b055de7f884de5cba1784909c5f1e6eb43 Mon Sep 17 00:00:00 2001 From: jrhee17 Date: Tue, 10 Dec 2019 01:05:16 +0900 Subject: [PATCH 07/10] introduce a QuicObjectDecoder --- .../handler/codec/quic/QuicObjectDecoder.java | 110 ++++++++++++++++++ .../codec/quic/QuicRequestDecoder.java | 10 +- .../codec/quic/QuicResponseDecoder.java | 103 +--------------- .../codec/quic/QuicRequestDecoderTest.java | 6 +- 4 files changed, 123 insertions(+), 106 deletions(-) create mode 100644 codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java new file mode 100644 index 000000000000..cf4f278aa32f --- /dev/null +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java @@ -0,0 +1,110 @@ +package io.netty.handler.codec.quic; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.socket.DatagramPacket; +import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.util.internal.logging.InternalLogger; +import io.netty.util.internal.logging.InternalLoggerFactory; + +public abstract class QuicObjectDecoder extends MessageToMessageDecoder { + private static final InternalLogger logger = InternalLoggerFactory.getInstance(QuicObjectDecoder.class); + + private enum State { + INITIAL, + HEADER, + DCID_LEN, + DCID, + SCID_LEN, + SCID, + } + + static int typeSpecificBits(byte b) { + return b & 0x0f; + } + + static short longPacketType(byte b) { + return (short) ((b & 0x30) >> 4); + } + + static boolean fixedBit(byte b) { + return (b & 0x40) >> 6 == 1; + } + + static boolean headerForm(byte b) { + return (b & 0x80) >> 7 == 1; + } + + private State state = State.INITIAL; + private int dcidLen; + private int scidLen; + private int version; + + protected boolean parseLongPacketHeader(ByteBuf byteBuf) { + switch (state) { + case INITIAL: + if (!byteBuf.isReadable()) { + return true; + } + final byte headerByte = byteBuf.readByte(); + final boolean headerForm = headerForm(headerByte); + + // only process long header packets for now... + if (!headerForm) { + logger.info("headerForm: {}", headerForm); + return true; + } + + final boolean fixedBit = fixedBit(headerByte); + final short longPacketType = longPacketType(headerByte); + final int typeSpecificBits = typeSpecificBits(headerByte); + logger.info("headerForm: {}, fixedBit: {}, longPacketType: {}, typeSpecificBits: {}", + headerForm, fixedBit, longPacketType, typeSpecificBits); + state = State.HEADER; + case HEADER: + if (!byteBuf.isReadable(4)) { + return true; + } + final ByteBuf versionByteBuf = byteBuf.readBytes(4); + version = versionByteBuf.readInt(); + logger.info("version: {}", version); + state = State.DCID_LEN; + case DCID_LEN: + if (!byteBuf.isReadable()) { + return true; + } + dcidLen = byteBuf.readByte(); + logger.info("dcidLen: {}", dcidLen); + state = State.DCID; + case DCID: + if (!byteBuf.isReadable()) { + return true; + } + final ByteBuf dcid = byteBuf.readBytes(dcidLen); + logger.info("dcid: {}", dcid); + state = State.SCID_LEN; + case SCID_LEN: + if (!byteBuf.isReadable()) { + return true; + } + scidLen = byteBuf.readByte(); + logger.info("scidLen: {}", scidLen); + state = State.SCID; + case SCID: + if (!byteBuf.isReadable()) { + return true; + } + final ByteBuf scid = byteBuf.readBytes(scidLen); + logger.info("scid: {}", scid); + } + + // it will be identified as a Version Negotiation packet based on the Version field having a value of 0 + if (version == 0) { + while (byteBuf.readableBytes() > 0) { + ByteBuf versionBytBuf = byteBuf.readBytes(4); + logger.info("supported version hexdump: {}", ByteBufUtil.hexDump(versionBytBuf)); + } + } + return false; + } +} diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java index e9c4eadb47c7..227e650ef44f 100644 --- a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequestDecoder.java @@ -1,15 +1,21 @@ package io.netty.handler.codec.quic; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.socket.DatagramPacket; -import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.util.ReferenceCountUtil; import java.util.List; -public class QuicRequestDecoder extends MessageToMessageDecoder { +public class QuicRequestDecoder extends QuicObjectDecoder { @Override protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List out) throws Exception { + + final ByteBuf content = msg.content(); + if (parseLongPacketHeader(content)) { + return; + } + out.add(new QuicMessage(ReferenceCountUtil.retain(msg.content()))); } } diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicResponseDecoder.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicResponseDecoder.java index e7d5d522d5e7..6381f9ebe2c0 100644 --- a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicResponseDecoder.java +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicResponseDecoder.java @@ -1,119 +1,22 @@ package io.netty.handler.codec.quic; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.socket.DatagramPacket; -import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.util.ReferenceCountUtil; -import io.netty.util.internal.logging.InternalLogger; -import io.netty.util.internal.logging.InternalLoggerFactory; import java.util.List; -public class QuicResponseDecoder extends MessageToMessageDecoder { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(QuicResponseDecoder.class); - - private enum State { - INITIAL, - HEADER, - DCID_LEN, - DCID, - SCID_LEN, - SCID, - } - - private State state = State.INITIAL; - private int dcidLen; - private int scidLen; - private int version; +public class QuicResponseDecoder extends QuicObjectDecoder { @Override protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List out) throws Exception { final ByteBuf byteBuf = msg.content(); - switch (state) { - case INITIAL: - if (!byteBuf.isReadable()) { - return; - } - final byte headerByte = byteBuf.readByte(); - final boolean headerForm = headerForm(headerByte); - - // only process long header packets for now... - if (!headerForm) { - logger.info("headerForm: {}", headerForm); - return; - } - - final boolean fixedBit = fixedBit(headerByte); - final short longPacketType = longPacketType(headerByte); - final int typeSpecificBits = typeSpecificBits(headerByte); - logger.info("headerForm: {}, fixedBit: {}, longPacketType: {}, typeSpecificBits: {}", - headerForm, fixedBit, longPacketType, typeSpecificBits); - state = State.HEADER; - case HEADER: - if (!byteBuf.isReadable(4)) { - return; - } - final ByteBuf versionByteBuf = byteBuf.readBytes(4); - version = versionByteBuf.readInt(); - logger.info("version: {}", version); - state = State.DCID_LEN; - case DCID_LEN: - if (!byteBuf.isReadable()) { - return; - } - dcidLen = byteBuf.readByte(); - logger.info("dcidLen: {}", dcidLen); - state = State.DCID; - case DCID: - if (!byteBuf.isReadable()) { - return; - } - final ByteBuf dcid = byteBuf.readBytes(dcidLen); - logger.info("dcid: {}", dcid); - state = State.SCID_LEN; - case SCID_LEN: - if (!byteBuf.isReadable()) { - return; - } - scidLen = byteBuf.readByte(); - logger.info("scidLen: {}", scidLen); - state = State.SCID; - case SCID: - if (!byteBuf.isReadable()) { - return; - } - final ByteBuf scid = byteBuf.readBytes(scidLen); - logger.info("scid: {}", scid); - } - - // it will be identified as a Version Negotiation packet based on the Version field having a value of 0 - if (version == 0) { - while (byteBuf.readableBytes() > 0) { - ByteBuf versionBytBuf = byteBuf.readBytes(4); - logger.info("supported version hexdump: {}", ByteBufUtil.hexDump(versionBytBuf)); - } + if (parseLongPacketHeader(byteBuf)) { + return; } out.add(new QuicMessage(ReferenceCountUtil.retain(byteBuf))); } - - static int typeSpecificBits(byte b) { - return b & 0x0f; - } - - static short longPacketType(byte b) { - return (short) ((b & 0x30) >> 4); - } - - static boolean fixedBit(byte b) { - return (b & 0x40) >> 6 == 1; - } - - static boolean headerForm(byte b) { - return (b & 0x80) >> 7 == 1; - } } diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java index 03dae65a0055..87911fe81e88 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java @@ -4,14 +4,11 @@ import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.channel.local.LocalAddress; import io.netty.channel.socket.DatagramPacket; import org.junit.Test; import java.net.InetSocketAddress; -import static org.junit.Assert.*; - public class QuicRequestDecoderTest { private static final String SAMPLE_INITIAL_HEXDUMP_PACKET = "cfff00001810b57f88e894e16fda41d0f29f49677f751477bc1a6f2950e4a601dd16df156bb93535e08711004482f6fff9222619c5ff07a85338139476ccda979adbc2f04e90fbbf8f8266af3005306fbba8b0f7dc6b89e0a4485ccfeaa8fe2d6c59bc0e1b376f6f02c5bc8ac90404bd7d2b3accd2c11e519092042957e9863a9ce927b7176f7536c46489ca7710b6e485b53edc43f44f5108f6a52d783a64d24857ba2ce24b5eeafe39cf02e8547fdb814e67d5c3c60045ce6c6a4f0113c895502c63f5c52c4c6dea34c91cc0691f6764507fc0f63af13a59728b063ada930234ba9b05f5f7d4add36b15028a2d892a55c798e96bbdc3bb91490cde96c9f37d336baa287584cc93101d5284ac340bbd29c3548c098532446e0bb95508fb878c33bc21a34273d15552a0fd450da2748700550ea33c187d0fd7bb0a94b57eb0803be430483118e8fe98fbeb8608436d8f39abe30c28fba360fc4675e401d64c1bd87bdfb647422a05432d7aaeeb600c85bbfbb99bda07deb2a5faf17f8c1b5de461fb6c41faa20338e54531b3080893af30c8aab269fef41051772df2b0a05ba393505b29c8b9edfd3085f359a64c2c8749aeb82e1ac7d0f3234af47b7ec9a51dbb81debbfc72490aad40c5377298d8cf0b21bf8f8750dfe3b45833f6a425d9cd8daaeb1aac1c44e69f198b5a9015364177bcba7f5022b6fdaf123de110360b0dd619a37dc96cbe2809df1e481a7e3b500911cb49c1bfe8dca4c6230ab816f187875a4c70198534f4e3e77ec76341f00135d3d7b701f3a1f2e6743b45d3af9a00fe4938fba2ab30cb3d3c67d0a237ab0be45e1229b72280bdec7e61c01da2329967a21ced88adc79e73818eb8aa583591c85f34dfe1231b70c5769cd8945bd642b607453c853b2061fd259b57e09743e54d6cd7b6344a1e9a817b94e2272f797a0a171ac14de318986bdf723eab648f3deeb4e18211f37e79a014e7b39ff07bf84b353936de53868f70a7a3d1be70186e741eeff84461afe9905a85ea18f0ec3586f332f3ef2db99921be70f2b89450b7e45b2ae381d4ef4e32abbfd5c11736da4c871bc7eacab8a5b7238925fd3cb8acd824de004b55bdc78bc6f518666772cd945444101d27f5141926246d7e8d95009ed2763d0bf88411f5eace577850d04d15e172116fc1fcd7d246d0a837627b6e7a610365e343d7544dd46c799daf74c05ed9c1a6b71c3598b9b4f7461f45cb88c6a6005269b9f8b1b3aefad2e7c3a12831d428337699fc414bde0320dc334ba06ac88c3522f8636b50c4bc15a1d088757c62882d5495b06d4d83fee1ecff34ab20f5e7003aae70a962d7ded730fc5ee75cb2fb8601429bec3211a70c194ba903bb38e1f182612dedfad96702c6cf55046fe04f89a3534d4006f288ffbd38d89dbbbd9d37ab5c188ee45264410f9fea51d393710b1ae834a80d91edda4aa63f60bfa582bb4451408f30b1e4dbef075b6f6554b7ac31ed7520158ee2fe7bff6a7038762826c6c40553f5b567f06fc75b3f387e9ddf3f1486348158868de7166679442cdee500ef61fb76dcf80d5a7c819831276e86d8736cdb21ee2aa22e0ca55c83bafc56e74be1ad935150653f6c34dd39bb67ab2357a873f0428df56d1c6f9a583c5feac8cfa71da32b8527d0de7baf725959b862b915bd091a7ea9ab6e4e72"; @@ -25,6 +22,7 @@ public void testEncoding() { final EmbeddedChannel channel = new EmbeddedChannel(new QuicRequestDecoder()); channel.writeInbound(datagramPacket); - assertTrue(channel.readInbound() instanceof QuicMessage); + final QuicMessage quicMessage = (QuicMessage) channel.readInbound(); + System.out.println(quicMessage); } } From b896746fcd0bb4bf922d385dc199f2f4f09b9f02 Mon Sep 17 00:00:00 2001 From: jrhee17 Date: Thu, 12 Dec 2019 01:03:20 +0900 Subject: [PATCH 08/10] start implementing varlen integer decoder --- .../handler/codec/quic/QuicObjectDecoder.java | 14 ++++++++------ .../io/netty/handler/codec/quic/QuicRequest.java | 14 ++++++++++++++ .../handler/codec/quic/QuicRequestDecoderTest.java | 2 +- .../netty/handler/codec/quic/QuicRequestTest.java | 9 +++++++++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java index cf4f278aa32f..dceeee637e0f 100644 --- a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java @@ -66,8 +66,8 @@ protected boolean parseLongPacketHeader(ByteBuf byteBuf) { return true; } final ByteBuf versionByteBuf = byteBuf.readBytes(4); - version = versionByteBuf.readInt(); - logger.info("version: {}", version); + version = versionByteBuf.copy().readInt(); + logger.info("version: {}", ByteBufUtil.prettyHexDump(versionByteBuf)); state = State.DCID_LEN; case DCID_LEN: if (!byteBuf.isReadable()) { @@ -77,11 +77,11 @@ protected boolean parseLongPacketHeader(ByteBuf byteBuf) { logger.info("dcidLen: {}", dcidLen); state = State.DCID; case DCID: - if (!byteBuf.isReadable()) { + if (!byteBuf.isReadable(dcidLen)) { return true; } final ByteBuf dcid = byteBuf.readBytes(dcidLen); - logger.info("dcid: {}", dcid); + logger.info("dcid: {}", ByteBufUtil.prettyHexDump(dcid)); state = State.SCID_LEN; case SCID_LEN: if (!byteBuf.isReadable()) { @@ -91,13 +91,15 @@ protected boolean parseLongPacketHeader(ByteBuf byteBuf) { logger.info("scidLen: {}", scidLen); state = State.SCID; case SCID: - if (!byteBuf.isReadable()) { + if (!byteBuf.isReadable(scidLen)) { return true; } final ByteBuf scid = byteBuf.readBytes(scidLen); - logger.info("scid: {}", scid); + logger.info("scid: {}", ByteBufUtil.prettyHexDump(scid)); } + logger.info("remaining bytes: {}", ByteBufUtil.prettyHexDump(byteBuf)); + // it will be identified as a Version Negotiation packet based on the Version field having a value of 0 if (version == 0) { while (byteBuf.readableBytes() > 0) { diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java index 63b1e1c3767d..a9f47c4a7ccd 100644 --- a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java @@ -87,4 +87,18 @@ static byte[] variableLengthIntegerEncoding(long length) { throw new IllegalArgumentException("invalid length: " + length); } } + + static int variableLengthIntegerDecoding(ByteBuf byteBuf) { + if (!byteBuf.isReadable()) { + throw new IllegalArgumentException("cannot read varint"); + } + final byte b = byteBuf.readByte(); + final int varIntLen = (b & 0xff) >> 6; + logger.info("varIntLen: {}", varIntLen); + if (varIntLen == 0) { + return b; + } + + return -1; + } } diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java index 87911fe81e88..433ab20b3a8b 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestDecoderTest.java @@ -22,7 +22,7 @@ public void testEncoding() { final EmbeddedChannel channel = new EmbeddedChannel(new QuicRequestDecoder()); channel.writeInbound(datagramPacket); - final QuicMessage quicMessage = (QuicMessage) channel.readInbound(); + final QuicMessage quicMessage = channel.readInbound(); System.out.println(quicMessage); } } diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java index 18c6c6ff15c8..f6bf1d45940a 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java @@ -1,6 +1,8 @@ package io.netty.handler.codec.quic; +import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; import org.junit.Test; import static org.junit.Assert.*; @@ -14,6 +16,13 @@ public void test1byteEncoding() { assertEquals("25", ByteBufUtil.hexDump(retval)); } + @Test + public void test1byteDecoding() { + final ByteBuf byteBuf = Unpooled.copiedBuffer(ByteBufUtil.decodeHexDump("25")); + final int result = QuicRequest.variableLengthIntegerDecoding(byteBuf); + assertEquals(37, result); + } + @Test public void test2byteEncoding() { final long length = 15293; From 31b133c2ddbdc66d7a0c9f1c74938a4b80c5578c Mon Sep 17 00:00:00 2001 From: John Date: Wed, 18 Dec 2019 00:35:05 +0900 Subject: [PATCH 09/10] implement varint encoding/decoding --- .../netty/handler/codec/quic/QuicRequest.java | 33 +++++++++++++++---- .../handler/codec/quic/QuicRequestTest.java | 23 ++++++++++++- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java index a9f47c4a7ccd..ae149de634a8 100644 --- a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicRequest.java @@ -88,17 +88,36 @@ static byte[] variableLengthIntegerEncoding(long length) { } } - static int variableLengthIntegerDecoding(ByteBuf byteBuf) { + static long variableLengthIntegerDecoding(ByteBuf byteBuf) { if (!byteBuf.isReadable()) { throw new IllegalArgumentException("cannot read varint"); } - final byte b = byteBuf.readByte(); - final int varIntLen = (b & 0xff) >> 6; - logger.info("varIntLen: {}", varIntLen); + final byte b1 = byteBuf.readByte(); + final int varIntLen = (b1 & 0xff) >> 6; if (varIntLen == 0) { - return b; + return b1 & 0xff >> 2; } - - return -1; + if (varIntLen == 1) { + final byte[] bytes = {b1, byteBuf.readByte()}; + return (bytes[0] & 0xff >> 2) << 8 | bytes[1] & 0xff; + } + if (varIntLen == 2) { + final byte[] bytes = {b1, byteBuf.readByte(), byteBuf.readByte(), byteBuf.readByte()}; + return (bytes[0] & 0xff >> 2) << 24 | (bytes[1] & 0xff) << 16 | + (bytes[2] & 0xff) << 8 | bytes[3] & 0xff; + } + if (varIntLen == 3) { + final byte[] bytes = {b1, byteBuf.readByte(), byteBuf.readByte(), byteBuf.readByte(), + byteBuf.readByte(), byteBuf.readByte(), byteBuf.readByte(), byteBuf.readByte()}; + return Long.valueOf(bytes[0] & 0xff >> 2) << 56 | + Long.valueOf(bytes[1] & 0xff) << 48 | + Long.valueOf(bytes[2] & 0xff) << 40 | + Long.valueOf(bytes[3] & 0xff) << 32 | + Long.valueOf(bytes[4] & 0xff) << 24 | + Long.valueOf(bytes[5] & 0xff) << 16 | + Long.valueOf(bytes[6] & 0xff) << 8 | + Long.valueOf(bytes[7] & 0xff); + } + throw new IllegalArgumentException("invalid length: " + varIntLen); } } diff --git a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java index f6bf1d45940a..3cf005f41723 100644 --- a/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java +++ b/codec-quic/src/test/java/io/netty/handler/codec/quic/QuicRequestTest.java @@ -19,7 +19,7 @@ public void test1byteEncoding() { @Test public void test1byteDecoding() { final ByteBuf byteBuf = Unpooled.copiedBuffer(ByteBufUtil.decodeHexDump("25")); - final int result = QuicRequest.variableLengthIntegerDecoding(byteBuf); + final long result = QuicRequest.variableLengthIntegerDecoding(byteBuf); assertEquals(37, result); } @@ -30,6 +30,13 @@ public void test2byteEncoding() { assertEquals("7bbd", ByteBufUtil.hexDump(retval)); } + @Test + public void test2byteDecoding() { + final ByteBuf byteBuf = Unpooled.copiedBuffer(ByteBufUtil.decodeHexDump("7bbd")); + final long result = QuicRequest.variableLengthIntegerDecoding(byteBuf); + assertEquals(15293, result); + } + @Test public void test4byteEncoding() { final long length = 494878333; @@ -37,10 +44,24 @@ public void test4byteEncoding() { assertEquals("9d7f3e7d", ByteBufUtil.hexDump(retval)); } + @Test + public void test4byteDecoding() { + final ByteBuf byteBuf = Unpooled.copiedBuffer(ByteBufUtil.decodeHexDump("9d7f3e7d")); + final long result = QuicRequest.variableLengthIntegerDecoding(byteBuf); + assertEquals(494878333, result); + } + @Test public void test8byteEncoding() { final long length = 151288809941952652L; final byte[] retval = QuicRequest.variableLengthIntegerEncoding(length); assertEquals("c2197c5eff14e88c", ByteBufUtil.hexDump(retval)); } + + @Test + public void test8byteDecoding() { + final ByteBuf byteBuf = Unpooled.copiedBuffer(ByteBufUtil.decodeHexDump("c2197c5eff14e88c")); + final long result = QuicRequest.variableLengthIntegerDecoding(byteBuf); + assertEquals(151288809941952652L, result); + } } From a92f3773ac34f8ed5ae299916a93061a9fe5b3d6 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 19 Dec 2019 00:25:28 +0900 Subject: [PATCH 10/10] read payload for initial packet --- .../handler/codec/quic/QuicObjectDecoder.java | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java index dceeee637e0f..a5f5a084a68b 100644 --- a/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java +++ b/codec-quic/src/main/java/io/netty/handler/codec/quic/QuicObjectDecoder.java @@ -17,6 +17,10 @@ private enum State { DCID, SCID_LEN, SCID, + TOKEN_LEN, + TOKEN, + LENGTH, + PAYLOAD, } static int typeSpecificBits(byte b) { @@ -35,10 +39,16 @@ static boolean headerForm(byte b) { return (b & 0x80) >> 7 == 1; } + private int packetNumLength; + private State state = State.INITIAL; private int dcidLen; private int scidLen; private int version; + private int tokenLen; + private ByteBuf token; + private int payloadLength; + private ByteBuf payload; protected boolean parseLongPacketHeader(ByteBuf byteBuf) { switch (state) { @@ -58,8 +68,9 @@ protected boolean parseLongPacketHeader(ByteBuf byteBuf) { final boolean fixedBit = fixedBit(headerByte); final short longPacketType = longPacketType(headerByte); final int typeSpecificBits = typeSpecificBits(headerByte); - logger.info("headerForm: {}, fixedBit: {}, longPacketType: {}, typeSpecificBits: {}", - headerForm, fixedBit, longPacketType, typeSpecificBits); + packetNumLength = headerByte & 0x3 + 1; + logger.info("headerForm: {}, fixedBit: {}, longPacketType: {}, typeSpecificBits: {}, packetNumLength: {}", + headerForm, fixedBit, longPacketType, typeSpecificBits, packetNumLength); state = State.HEADER; case HEADER: if (!byteBuf.isReadable(4)) { @@ -96,8 +107,41 @@ protected boolean parseLongPacketHeader(ByteBuf byteBuf) { } final ByteBuf scid = byteBuf.readBytes(scidLen); logger.info("scid: {}", ByteBufUtil.prettyHexDump(scid)); + case TOKEN_LEN: + if (!byteBuf.isReadable()) { + return true; + } + tokenLen = (int) QuicRequest.variableLengthIntegerDecoding(byteBuf); + logger.info("tokenLen: {}", tokenLen); + case TOKEN: + if (!byteBuf.isReadable(tokenLen)) { + return true; + } + token = byteBuf.readBytes(tokenLen); + logger.info("token: {}", token); + case LENGTH: + if (!byteBuf.isReadable()) { + return true; + } + payloadLength = (int) QuicRequest.variableLengthIntegerDecoding(byteBuf); + logger.info("payloadLength: {}", payloadLength); + case PAYLOAD: + if (!byteBuf.isReadable(payloadLength)) { + return true; + } + payload = byteBuf.readBytes(payloadLength); + logger.info("payload: {}", ByteBufUtil.prettyHexDump(payload)); } + ByteBuf copiedPayload = payload.copy(); + ByteBuf packetNumber = copiedPayload.readBytes(packetNumLength); + logger.info("packetNumber: {}", ByteBufUtil.prettyHexDump(packetNumber)); + + logger.info("first byte: {}", Integer.toBinaryString(copiedPayload.getByte(copiedPayload.readerIndex()) & 0xff)); + logger.info("first byte: {}", Integer.toHexString(copiedPayload.getByte(copiedPayload.readerIndex()) & 0xff)); + int firstFrameType = (int) QuicRequest.variableLengthIntegerDecoding(copiedPayload); + logger.info("firstFrameType: {}", firstFrameType); + logger.info("remaining bytes: {}", ByteBufUtil.prettyHexDump(byteBuf)); // it will be identified as a Version Negotiation packet based on the Version field having a value of 0