misc cleanups and improvements

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2021-03-16 10:16:28 +01:00 committed by Simone Bordet
parent add0c8b605
commit e370f5e0ba
1 changed files with 60 additions and 40 deletions

View File

@ -3,8 +3,8 @@ package org.eclipse.jetty.http3.server;
import java.io.File; import java.io.File;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -16,6 +16,7 @@ import org.eclipse.jetty.http3.quiche.ffi.LibQuiche;
import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -44,6 +45,7 @@ public class QuicConnection extends AbstractConnection
throw new RuntimeException(e); throw new RuntimeException(e);
} }
// TODO make the QuicheConfig configurable
quicheConfig = new QuicheConfig(); quicheConfig = new QuicheConfig();
quicheConfig.setPrivKeyPemPath(files[0].getPath()); quicheConfig.setPrivKeyPemPath(files[0].getPath());
quicheConfig.setCertChainPemPath(files[1].getPath()); quicheConfig.setCertChainPemPath(files[1].getPath());
@ -60,7 +62,8 @@ public class QuicConnection extends AbstractConnection
private Collection<String> getProtocols() private Collection<String> getProtocols()
{ {
return Arrays.asList("http/0.9"); // TODO get the protocols from the connector
return Collections.singletonList("http/0.9");
} }
@Override @Override
@ -75,55 +78,72 @@ public class QuicConnection extends AbstractConnection
{ {
try try
{ {
ByteBuffer buffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN + ServerDatagramEndPoint.ENCODED_ADDRESS_LENGTH, true); ByteBuffer cipherBuffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN + ServerDatagramEndPoint.ENCODED_ADDRESS_LENGTH, true);
// Read data BufferUtil.flipToFill(cipherBuffer);
int fill = getEndPoint().fill(buffer); while (true)
if (fill < 0)
{ {
byteBufferPool.release(buffer); // Read data
getEndPoint().shutdownOutput(); int fill = getEndPoint().fill(cipherBuffer);
return; // TODO ServerDatagramEndPoint will never return -1 to fill b/c of UDP
} if (fill < 0)
if (fill == 0) {
{ byteBufferPool.release(cipherBuffer);
byteBufferPool.release(buffer); getEndPoint().shutdownOutput();
fillInterested(); return;
return; }
} if (fill == 0)
{
byteBufferPool.release(cipherBuffer);
fillInterested();
return;
}
InetSocketAddress remoteAddress = ServerDatagramEndPoint.decodeInetSocketAddress(buffer); InetSocketAddress remoteAddress = ServerDatagramEndPoint.decodeInetSocketAddress(cipherBuffer);
QuicheConnectionId quicheConnectionId = QuicheConnectionId.fromPacket(buffer); QuicheConnectionId quicheConnectionId = QuicheConnectionId.fromPacket(cipherBuffer);
QuicheConnection quicheConnection = connections.get(quicheConnectionId); QuicheConnection quicheConnection = connections.get(quicheConnectionId);
if (quicheConnection == null)
{
quicheConnection = QuicheConnection.tryAccept(quicheConfig, remoteAddress, buffer);
if (quicheConnection == null) if (quicheConnection == null)
{ {
ByteBuffer address = byteBufferPool.acquire(ServerDatagramEndPoint.ENCODED_ADDRESS_LENGTH, true); quicheConnection = QuicheConnection.tryAccept(quicheConfig, remoteAddress, cipherBuffer);
BufferUtil.flipToFill(address); if (quicheConnection == null)
ServerDatagramEndPoint.encodeInetSocketAddress(address, remoteAddress); {
address.flip(); ByteBuffer addressBuffer = byteBufferPool.acquire(ServerDatagramEndPoint.ENCODED_ADDRESS_LENGTH, true);
BufferUtil.flipToFill(addressBuffer);
ServerDatagramEndPoint.encodeInetSocketAddress(addressBuffer, remoteAddress);
addressBuffer.flip();
ByteBuffer buffer2 = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN, true); ByteBuffer negotiationBuffer = byteBufferPool.acquire(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN, true);
BufferUtil.flipToFill(buffer2); BufferUtil.flipToFill(negotiationBuffer);
QuicheConnection.negotiate(remoteAddress, buffer, buffer2); QuicheConnection.negotiate(remoteAddress, cipherBuffer, negotiationBuffer);
negotiationBuffer.flip();
getEndPoint().flush(address, buffer2); getEndPoint().write(new Callback() {
byteBufferPool.release(address); @Override
byteBufferPool.release(buffer2); public void succeeded()
{
byteBufferPool.release(addressBuffer);
byteBufferPool.release(negotiationBuffer);
}
@Override
public void failed(Throwable x)
{
byteBufferPool.release(addressBuffer);
byteBufferPool.release(negotiationBuffer);
}
}, addressBuffer, negotiationBuffer);
}
else
{
LOG.info("Quic connection accepted");
connections.put(quicheConnectionId, quicheConnection);
}
} }
else else
{ {
LOG.info("Quic connection accepted"); quicheConnection.feedCipherText(cipherBuffer);
connections.put(quicheConnectionId, quicheConnection);
} }
BufferUtil.clearToFill(cipherBuffer);
} }
else
{
quicheConnection.feedCipherText(buffer);
}
byteBufferPool.release(buffer);
fillInterested();
} }
catch (Throwable x) catch (Throwable x)
{ {