improve quiche error handling

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2021-03-26 14:55:33 +01:00 committed by Simone Bordet
parent 4455291bf9
commit c70f49c773
4 changed files with 23 additions and 16 deletions

View File

@ -73,16 +73,16 @@ public class ClientQuicConnection extends QuicConnection
} }
@Override @Override
protected void onClose(QuicheConnectionId quicheConnectionId, QuicSession session) protected void closeSession(QuicheConnectionId quicheConnectionId, QuicSession session, Throwable x)
{ {
super.onClose(quicheConnectionId, session); super.closeSession(quicheConnectionId, session, x);
InetSocketAddress remoteAddress = session.getRemoteAddress(); InetSocketAddress remoteAddress = session.getRemoteAddress();
if (pendingSessions.remove(remoteAddress) != null) if (pendingSessions.remove(remoteAddress) != null)
{ {
Promise<?> promise = (Promise<?>)context.get(ClientConnector.CONNECTION_PROMISE_CONTEXT_KEY); Promise<?> promise = (Promise<?>)context.get(ClientConnector.CONNECTION_PROMISE_CONTEXT_KEY);
if (promise != null) if (promise != null)
promise.failed(new IOException("QUIC connection refused")); promise.failed(x);
} }
} }

View File

@ -59,8 +59,6 @@ public class ClientQuicConnector extends ClientConnector
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
{ {
//TODO: when the ALPN protos aren't set, the client freezes. Investigate & fix.
//TODO: what is the best place to create the quiche config? //TODO: what is the best place to create the quiche config?
// TODO detect the ALPN protos // TODO detect the ALPN protos

View File

@ -60,7 +60,7 @@ public abstract class QuicConnection extends AbstractConnection
return byteBufferPool; return byteBufferPool;
} }
protected void onClose(QuicheConnectionId quicheConnectionId, QuicSession session) protected void closeSession(QuicheConnectionId quicheConnectionId, QuicSession session, Throwable x)
{ {
if (quicheConnectionId != null) if (quicheConnectionId != null)
sessions.remove(quicheConnectionId); sessions.remove(quicheConnectionId);

View File

@ -231,6 +231,14 @@ public abstract class QuicSession
protected abstract QuicStreamEndPoint createQuicStreamEndPoint(long streamId); protected abstract QuicStreamEndPoint createQuicStreamEndPoint(long streamId);
public void close() public void close()
{
if (quicheConnectionId == null)
close(new IOException("Quic connection refused"));
else
close(new IOException("Quic connection closed"));
}
public void close(Throwable x)
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("closing QUIC session {}", this); LOG.debug("closing QUIC session {}", this);
@ -239,7 +247,7 @@ public abstract class QuicSession
endpoints.values().forEach(AbstractEndPoint::close); endpoints.values().forEach(AbstractEndPoint::close);
endpoints.clear(); endpoints.clear();
flusher.close(); flusher.close();
connection.onClose(quicheConnectionId, this); connection.closeSession(quicheConnectionId, this, x);
LifeCycle.stop(strategy); LifeCycle.stop(strategy);
} }
finally finally
@ -300,15 +308,7 @@ public abstract class QuicSession
else else
timeout.schedule(nextTimeoutInMs, TimeUnit.MILLISECONDS); timeout.schedule(nextTimeoutInMs, TimeUnit.MILLISECONDS);
if (drained == 0) if (drained == 0)
{ return quicheConnection.isConnectionClosed() ? Action.SUCCEEDED : Action.IDLE;
if (quicheConnection.isConnectionClosed())
{
if (LOG.isDebugEnabled())
LOG.debug("quiche connection is in closed state");
QuicSession.this.close();
}
return Action.IDLE;
}
BufferUtil.flipToFlush(cipherBuffer, pos); BufferUtil.flipToFlush(cipherBuffer, pos);
connection.write(this, remoteAddress, cipherBuffer); connection.write(this, remoteAddress, cipherBuffer);
return Action.SCHEDULED; return Action.SCHEDULED;
@ -321,10 +321,19 @@ public abstract class QuicSession
super.succeeded(); super.succeeded();
} }
@Override
protected void onCompleteSuccess()
{
if (LOG.isDebugEnabled())
LOG.debug("quiche connection is in closed state");
QuicSession.this.close();
}
@Override @Override
protected void onCompleteFailure(Throwable cause) protected void onCompleteFailure(Throwable cause)
{ {
byteBufferPool.release(cipherBuffer); byteBufferPool.release(cipherBuffer);
QuicSession.this.close(cause);
} }
} }
} }