factor out address decoding and encoding

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2021-03-17 14:22:50 +01:00 committed by Simone Bordet
parent 44eb359d57
commit 36c0f79a94
4 changed files with 90 additions and 56 deletions

View File

@ -0,0 +1,81 @@
//
// ========================================================================
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.http3.server;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
public class AddressCodec
{
public static final int ENCODED_ADDRESS_LENGTH = 19;
public static ByteBuffer encodeInetSocketAddress(ByteBufferPool byteBufferPool, InetSocketAddress remoteAddress) throws IOException
{
ByteBuffer addressBuffer = byteBufferPool.acquire(ENCODED_ADDRESS_LENGTH, true);
try
{
int pos = BufferUtil.flipToFill(addressBuffer);
encodeInetSocketAddress(addressBuffer, remoteAddress);
BufferUtil.flipToFlush(addressBuffer, pos);
return addressBuffer;
}
catch (Throwable x)
{
byteBufferPool.release(addressBuffer);
throw x;
}
}
public static InetSocketAddress decodeInetSocketAddress(ByteBuffer buffer) throws IOException
{
int headerPosition = buffer.position();
byte ipVersion = buffer.get();
byte[] address;
if (ipVersion == 4)
address = new byte[4];
else if (ipVersion == 6)
address = new byte[16];
else
throw new IOException("Unsupported IP version: " + ipVersion);
buffer.get(address);
int port = buffer.getChar();
buffer.position(headerPosition + ENCODED_ADDRESS_LENGTH);
return new InetSocketAddress(InetAddress.getByAddress(address), port);
}
public static void encodeInetSocketAddress(ByteBuffer buffer, InetSocketAddress peer) throws IOException
{
int headerPosition = buffer.position();
byte[] addressBytes = peer.getAddress().getAddress();
int port = peer.getPort();
byte ipVersion;
if (peer.getAddress() instanceof Inet4Address)
ipVersion = 4;
else if (peer.getAddress() instanceof Inet6Address)
ipVersion = 6;
else
throw new IOException("Unsupported address type: " + peer.getAddress().getClass());
buffer.put(ipVersion);
buffer.put(addressBytes);
buffer.putChar((char)port);
buffer.position(headerPosition + ENCODED_ADDRESS_LENGTH);
}
}

View File

@ -14,7 +14,6 @@
package org.eclipse.jetty.http3.server;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
@ -104,7 +103,7 @@ public class QuicConnection extends AbstractConnection
{
try
{
ByteBuffer cipherBuffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN + ServerDatagramEndPoint.ENCODED_ADDRESS_LENGTH, true);
ByteBuffer cipherBuffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN + AddressCodec.ENCODED_ADDRESS_LENGTH, true);
while (true)
{
int fill = getEndPoint().fill(cipherBuffer);
@ -118,7 +117,7 @@ public class QuicConnection extends AbstractConnection
if (LOG.isDebugEnabled())
LOG.debug("received buffer(address+ciphertext) of size {}", cipherBuffer.remaining());
InetSocketAddress remoteAddress = ServerDatagramEndPoint.decodeInetSocketAddress(cipherBuffer);
InetSocketAddress remoteAddress = AddressCodec.decodeInetSocketAddress(cipherBuffer);
if (LOG.isDebugEnabled())
LOG.debug("decoded peer IP address: {}, ciphertext packet size: {}", remoteAddress, cipherBuffer.remaining());
@ -141,7 +140,7 @@ public class QuicConnection extends AbstractConnection
QuicheConnection quicheConnection = QuicheConnection.tryAccept(quicheConfig, remoteAddress, cipherBuffer);
if (quicheConnection == null)
{
ByteBuffer addressBuffer = encodeInetSocketAddress(byteBufferPool, remoteAddress);
ByteBuffer addressBuffer = AddressCodec.encodeInetSocketAddress(byteBufferPool, remoteAddress);
ByteBuffer negotiationBuffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN, true);
int pos = BufferUtil.flipToFill(negotiationBuffer);
@ -191,15 +190,6 @@ public class QuicConnection extends AbstractConnection
flusher.iterate();
}
static ByteBuffer encodeInetSocketAddress(ByteBufferPool byteBufferPool, InetSocketAddress remoteAddress) throws IOException
{
ByteBuffer addressBuffer = byteBufferPool.acquire(ServerDatagramEndPoint.ENCODED_ADDRESS_LENGTH, true);
int pos = BufferUtil.flipToFill(addressBuffer);
ServerDatagramEndPoint.encodeInetSocketAddress(addressBuffer, remoteAddress);
BufferUtil.flipToFlush(addressBuffer, pos);
return addressBuffer;
}
private class Flusher extends IteratingCallback
{
private final AutoLock lock = new AutoLock();

View File

@ -239,8 +239,8 @@ public class QuicSession
protected Action process() throws IOException
{
ByteBufferPool byteBufferPool = connector.getByteBufferPool();
addressBuffer = QuicConnection.encodeInetSocketAddress(byteBufferPool, remoteAddress);
cipherBuffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN + ServerDatagramEndPoint.ENCODED_ADDRESS_LENGTH, true);
addressBuffer = AddressCodec.encodeInetSocketAddress(byteBufferPool, remoteAddress);
cipherBuffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN + AddressCodec.ENCODED_ADDRESS_LENGTH, true);
int pos = BufferUtil.flipToFill(cipherBuffer);
int drained = quicheConnection.drainCipherText(cipherBuffer);
long nextTimeoutInMs = quicheConnection.nextTimeout();

View File

@ -41,8 +41,6 @@ import org.slf4j.LoggerFactory;
public class ServerDatagramEndPoint extends IdleTimeout implements EndPoint, ManagedSelector.Selectable
{
private static final Logger LOG = LoggerFactory.getLogger(ServerDatagramEndPoint.class);
// TODO: javadocs
static final int ENCODED_ADDRESS_LENGTH = 19;
private final long createdTimeStamp = System.currentTimeMillis();
private final AtomicBoolean fillable = new AtomicBoolean();
@ -138,7 +136,7 @@ public class ServerDatagramEndPoint extends IdleTimeout implements EndPoint, Man
{
int pos = BufferUtil.flipToFill(buffer);
buffer.position(pos + ENCODED_ADDRESS_LENGTH);
buffer.position(pos + AddressCodec.ENCODED_ADDRESS_LENGTH);
InetSocketAddress peer = (InetSocketAddress)channel.receive(buffer);
if (peer == null)
{
@ -149,18 +147,18 @@ public class ServerDatagramEndPoint extends IdleTimeout implements EndPoint, Man
int finalPosition = buffer.position();
buffer.position(pos);
encodeInetSocketAddress(buffer, peer);
AddressCodec.encodeInetSocketAddress(buffer, peer);
buffer.position(finalPosition);
BufferUtil.flipToFlush(buffer, pos);
return finalPosition - ENCODED_ADDRESS_LENGTH;
return finalPosition - AddressCodec.ENCODED_ADDRESS_LENGTH;
}
@Override
public boolean flush(ByteBuffer... buffers) throws IOException
{
InetSocketAddress peer = decodeInetSocketAddress(buffers[0]);
InetSocketAddress peer = AddressCodec.decodeInetSocketAddress(buffers[0]);
for (int i = 1; i < buffers.length; i++)
{
ByteBuffer buffer = buffers[i];
@ -276,39 +274,4 @@ public class ServerDatagramEndPoint extends IdleTimeout implements EndPoint, Man
{
throw new UnsupportedOperationException();
}
static InetSocketAddress decodeInetSocketAddress(ByteBuffer buffer) throws IOException
{
int headerPosition = buffer.position();
byte ipVersion = buffer.get();
byte[] address;
if (ipVersion == 4)
address = new byte[4];
else if (ipVersion == 6)
address = new byte[16];
else
throw new IOException("Unsupported IP version: " + ipVersion);
buffer.get(address);
int port = buffer.getChar();
buffer.position(headerPosition + ENCODED_ADDRESS_LENGTH);
return new InetSocketAddress(InetAddress.getByAddress(address), port);
}
static void encodeInetSocketAddress(ByteBuffer buffer, InetSocketAddress peer) throws IOException
{
int headerPosition = buffer.position();
byte[] addressBytes = peer.getAddress().getAddress();
int port = peer.getPort();
byte ipVersion;
if (peer.getAddress() instanceof Inet4Address)
ipVersion = 4;
else if (peer.getAddress() instanceof Inet6Address)
ipVersion = 6;
else
throw new IOException("Unsupported address type: " + peer.getAddress().getClass());
buffer.put(ipVersion);
buffer.put(addressBytes);
buffer.putChar((char)port);
buffer.position(headerPosition + ENCODED_ADDRESS_LENGTH);
}
}