Skip to content

Commit

Permalink
Fixes #5888 - Limit usage of HTTP/2 connections. (#12401)
Browse files Browse the repository at this point in the history
* Made the high-level HttpConnectionOverHTTP2 implement MaxUsable, so it cannot be used to open more streams than allowed.
* Introduced HTTP2Session.maxTotalLocalStreams to limit the max number of streams that might be created in a connection. Linked this new property with the high-level AbstractConnectionPool.maxUsage.
* Implemented low-level handling of explicit stream ids provided by applications.
* Implemented low-level handling of stream id overflow.
* Added test cases.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
Co-authored-by: Ludovic Orban <lorban@bitronix.be>
  • Loading branch information
sbordet and lorban authored Oct 31, 2024
1 parent 94c3f9d commit b9cdfd3
Show file tree
Hide file tree
Showing 6 changed files with 361 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ protected Connection activate()

int maxUsage = getMaxUsage();
if (connection instanceof MaxUsable maxUsable)
maxUsage = maxUsable.getMaxUsage();
maxUsage = Math.min(maxUsage, maxUsable.getMaxUsage());
if (maxUsage > 0)
{
EntryHolder holder = (EntryHolder)((Attachable)connection).getAttachment();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicMarkableReference;

import org.eclipse.jetty.client.AbstractConnectionPool;
import org.eclipse.jetty.client.Connection;
import org.eclipse.jetty.client.ConnectionPool;
import org.eclipse.jetty.client.Destination;
import org.eclipse.jetty.client.HttpClientTransport;
import org.eclipse.jetty.http2.HTTP2Connection;
Expand Down Expand Up @@ -73,10 +75,15 @@ public void onSettings(Session session, SettingsFrame frame)

private void onServerPreface(Session session)
{
Destination destination = destination();
HTTP2Connection http2Connection = (HTTP2Connection)context.get(HTTP2Connection.class.getName());
HttpConnectionOverHTTP2 connection = (HttpConnectionOverHTTP2)newConnection(destination(), session, http2Connection);
HttpConnectionOverHTTP2 connection = (HttpConnectionOverHTTP2)newConnection(destination, session, http2Connection);
if (this.connection.compareAndSet(null, connection, false, true))
{
ConnectionPool connectionPool = destination.getConnectionPool();
if (connectionPool instanceof AbstractConnectionPool pool)
connection.setMaxUsage(pool.getMaxUsage());

// The connection promise must be called synchronously
// so that the HTTP/1 to HTTP/2 upgrade can create the
// HTTP/2 stream that represents the HTTP/1 request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HttpConnectionOverHTTP2 extends HttpConnection implements Sweeper.Sweepable, ConnectionPool.MaxMultiplexable
public class HttpConnectionOverHTTP2 extends HttpConnection implements Sweeper.Sweepable, ConnectionPool.MaxMultiplexable, ConnectionPool.MaxUsable
{
private static final Logger LOG = LoggerFactory.getLogger(HttpConnectionOverHTTP2.class);

Expand Down Expand Up @@ -108,6 +108,17 @@ public int getMaxMultiplex()
return ((HTTP2Session)session).getMaxLocalStreams();
}

@Override
public int getMaxUsage()
{
return ((HTTP2Session)session).getMaxTotalLocalStreams();
}

void setMaxUsage(int maxUsage)
{
((HTTP2Session)session).setMaxTotalLocalStreams(maxUsage);
}

@Override
protected Iterator<HttpChannel> getHttpChannels()
{
Expand Down
Loading

0 comments on commit b9cdfd3

Please sign in to comment.