Merged branch 'jetty-9.3.x' into 'master'.
This commit is contained in:
commit
802948259e
|
@ -30,6 +30,7 @@ import java.util.Map;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory;
|
import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory;
|
||||||
|
import org.eclipse.jetty.http2.FlowControlStrategy;
|
||||||
import org.eclipse.jetty.http2.api.Session;
|
import org.eclipse.jetty.http2.api.Session;
|
||||||
import org.eclipse.jetty.io.ByteBufferPool;
|
import org.eclipse.jetty.io.ByteBufferPool;
|
||||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||||
|
@ -41,6 +42,8 @@ import org.eclipse.jetty.io.SelectorManager;
|
||||||
import org.eclipse.jetty.io.SocketChannelEndPoint;
|
import org.eclipse.jetty.io.SocketChannelEndPoint;
|
||||||
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
|
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
|
||||||
import org.eclipse.jetty.util.Promise;
|
import org.eclipse.jetty.util.Promise;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
@ -107,6 +110,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
||||||
* client.stop();
|
* client.stop();
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
|
@ManagedObject
|
||||||
public class HTTP2Client extends ContainerLifeCycle
|
public class HTTP2Client extends ContainerLifeCycle
|
||||||
{
|
{
|
||||||
private Executor executor;
|
private Executor executor;
|
||||||
|
@ -117,7 +121,10 @@ public class HTTP2Client extends ContainerLifeCycle
|
||||||
private int selectors = 1;
|
private int selectors = 1;
|
||||||
private long idleTimeout = 30000;
|
private long idleTimeout = 30000;
|
||||||
private long connectTimeout = 10000;
|
private long connectTimeout = 10000;
|
||||||
|
private int inputBufferSize = 8192;
|
||||||
private List<String> protocols = Arrays.asList("h2", "h2-17", "h2-16", "h2-15", "h2-14");
|
private List<String> protocols = Arrays.asList("h2", "h2-17", "h2-16", "h2-15", "h2-14");
|
||||||
|
private int initialSessionRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
|
||||||
|
private int initialStreamRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doStart() throws Exception
|
protected void doStart() throws Exception
|
||||||
|
@ -134,13 +141,15 @@ public class HTTP2Client extends ContainerLifeCycle
|
||||||
if (connectionFactory == null)
|
if (connectionFactory == null)
|
||||||
{
|
{
|
||||||
HTTP2ClientConnectionFactory h2 = new HTTP2ClientConnectionFactory();
|
HTTP2ClientConnectionFactory h2 = new HTTP2ClientConnectionFactory();
|
||||||
ALPNClientConnectionFactory alpn = new ALPNClientConnectionFactory(getExecutor(), h2, getProtocols());
|
|
||||||
setClientConnectionFactory((endPoint, context) ->
|
setClientConnectionFactory((endPoint, context) ->
|
||||||
{
|
{
|
||||||
ClientConnectionFactory factory = h2;
|
ClientConnectionFactory factory = h2;
|
||||||
SslContextFactory sslContextFactory = (SslContextFactory)context.get(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY);
|
SslContextFactory sslContextFactory = (SslContextFactory)context.get(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY);
|
||||||
if (sslContextFactory != null)
|
if (sslContextFactory != null)
|
||||||
|
{
|
||||||
|
ALPNClientConnectionFactory alpn = new ALPNClientConnectionFactory(getExecutor(), h2, getProtocols());
|
||||||
factory = new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), alpn);
|
factory = new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), alpn);
|
||||||
|
}
|
||||||
return factory.newConnection(endPoint, context);
|
return factory.newConnection(endPoint, context);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -204,6 +213,7 @@ public class HTTP2Client extends ContainerLifeCycle
|
||||||
this.connectionFactory = connectionFactory;
|
this.connectionFactory = connectionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The number of selectors")
|
||||||
public int getSelectors()
|
public int getSelectors()
|
||||||
{
|
{
|
||||||
return selectors;
|
return selectors;
|
||||||
|
@ -214,6 +224,7 @@ public class HTTP2Client extends ContainerLifeCycle
|
||||||
this.selectors = selectors;
|
this.selectors = selectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The idle timeout in milliseconds")
|
||||||
public long getIdleTimeout()
|
public long getIdleTimeout()
|
||||||
{
|
{
|
||||||
return idleTimeout;
|
return idleTimeout;
|
||||||
|
@ -224,6 +235,7 @@ public class HTTP2Client extends ContainerLifeCycle
|
||||||
this.idleTimeout = idleTimeout;
|
this.idleTimeout = idleTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The connect timeout in milliseconds")
|
||||||
public long getConnectTimeout()
|
public long getConnectTimeout()
|
||||||
{
|
{
|
||||||
return connectTimeout;
|
return connectTimeout;
|
||||||
|
@ -237,6 +249,18 @@ public class HTTP2Client extends ContainerLifeCycle
|
||||||
selector.setConnectTimeout(connectTimeout);
|
selector.setConnectTimeout(connectTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The size of the buffer used to read from the network")
|
||||||
|
public int getInputBufferSize()
|
||||||
|
{
|
||||||
|
return inputBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputBufferSize(int inputBufferSize)
|
||||||
|
{
|
||||||
|
this.inputBufferSize = inputBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The ALPN protocol list")
|
||||||
public List<String> getProtocols()
|
public List<String> getProtocols()
|
||||||
{
|
{
|
||||||
return protocols;
|
return protocols;
|
||||||
|
@ -247,6 +271,28 @@ public class HTTP2Client extends ContainerLifeCycle
|
||||||
this.protocols = protocols;
|
this.protocols = protocols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The initial size of session's flow control receive window")
|
||||||
|
public int getInitialSessionRecvWindow()
|
||||||
|
{
|
||||||
|
return initialSessionRecvWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialSessionRecvWindow(int initialSessionRecvWindow)
|
||||||
|
{
|
||||||
|
this.initialSessionRecvWindow = initialSessionRecvWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The initial size of stream's flow control receive window")
|
||||||
|
public int getInitialStreamRecvWindow()
|
||||||
|
{
|
||||||
|
return initialStreamRecvWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialStreamRecvWindow(int initialStreamRecvWindow)
|
||||||
|
{
|
||||||
|
this.initialStreamRecvWindow = initialStreamRecvWindow;
|
||||||
|
}
|
||||||
|
|
||||||
public void connect(InetSocketAddress address, Session.Listener listener, Promise<Session> promise)
|
public void connect(InetSocketAddress address, Session.Listener listener, Promise<Session> promise)
|
||||||
{
|
{
|
||||||
connect(null, address, listener, promise);
|
connect(null, address, listener, promise);
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.eclipse.jetty.io.Connection;
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
import org.eclipse.jetty.io.EndPoint;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.Promise;
|
import org.eclipse.jetty.util.Promise;
|
||||||
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
import org.eclipse.jetty.util.thread.Scheduler;
|
import org.eclipse.jetty.util.thread.Scheduler;
|
||||||
|
|
||||||
public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
||||||
|
@ -50,7 +51,7 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
||||||
public static final String SESSION_LISTENER_CONTEXT_KEY = "http2.client.sessionListener";
|
public static final String SESSION_LISTENER_CONTEXT_KEY = "http2.client.sessionListener";
|
||||||
public static final String SESSION_PROMISE_CONTEXT_KEY = "http2.client.sessionPromise";
|
public static final String SESSION_PROMISE_CONTEXT_KEY = "http2.client.sessionPromise";
|
||||||
|
|
||||||
private int initialSessionRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
|
private final Connection.Listener connectionListener = new ConnectionListener();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
|
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
|
||||||
|
@ -67,7 +68,9 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
||||||
FlowControlStrategy flowControl = newFlowControlStrategy();
|
FlowControlStrategy flowControl = newFlowControlStrategy();
|
||||||
HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl);
|
HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl);
|
||||||
Parser parser = new Parser(byteBufferPool, session, 4096, 8192);
|
Parser parser = new Parser(byteBufferPool, session, 4096, 8192);
|
||||||
return new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint, parser, session, 8192, promise, listener);
|
HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint, parser, session, client.getInputBufferSize(), promise, listener);
|
||||||
|
connection.addListener(connectionListener);
|
||||||
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FlowControlStrategy newFlowControlStrategy()
|
protected FlowControlStrategy newFlowControlStrategy()
|
||||||
|
@ -75,16 +78,6 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
||||||
return new BufferingFlowControlStrategy(0.5F);
|
return new BufferingFlowControlStrategy(0.5F);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInitialSessionRecvWindow()
|
|
||||||
{
|
|
||||||
return initialSessionRecvWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInitialSessionRecvWindow(int initialSessionRecvWindow)
|
|
||||||
{
|
|
||||||
this.initialSessionRecvWindow = initialSessionRecvWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class HTTP2ClientConnection extends HTTP2Connection implements Callback
|
private class HTTP2ClientConnection extends HTTP2Connection implements Callback
|
||||||
{
|
{
|
||||||
private final HTTP2Client client;
|
private final HTTP2Client client;
|
||||||
|
@ -108,8 +101,10 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
||||||
|
|
||||||
PrefaceFrame prefaceFrame = new PrefaceFrame();
|
PrefaceFrame prefaceFrame = new PrefaceFrame();
|
||||||
SettingsFrame settingsFrame = new SettingsFrame(settings, false);
|
SettingsFrame settingsFrame = new SettingsFrame(settings, false);
|
||||||
|
|
||||||
ISession session = getSession();
|
ISession session = getSession();
|
||||||
int windowDelta = getInitialSessionRecvWindow() - FlowControlStrategy.DEFAULT_WINDOW_SIZE;
|
|
||||||
|
int windowDelta = client.getInitialSessionRecvWindow() - FlowControlStrategy.DEFAULT_WINDOW_SIZE;
|
||||||
if (windowDelta > 0)
|
if (windowDelta > 0)
|
||||||
{
|
{
|
||||||
session.updateRecvWindow(windowDelta);
|
session.updateRecvWindow(windowDelta);
|
||||||
|
@ -138,4 +133,21 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
|
||||||
promise.failed(x);
|
promise.failed(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ConnectionListener implements Connection.Listener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onOpened(Connection connection)
|
||||||
|
{
|
||||||
|
HTTP2ClientConnection http2Connection = (HTTP2ClientConnection)connection;
|
||||||
|
http2Connection.client.addManaged((LifeCycle)http2Connection.getSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClosed(Connection connection)
|
||||||
|
{
|
||||||
|
HTTP2ClientConnection http2Connection = (HTTP2ClientConnection)connection;
|
||||||
|
http2Connection.client.removeBean(http2Connection.getSession());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.http2.client;
|
||||||
import org.eclipse.jetty.http2.FlowControlStrategy;
|
import org.eclipse.jetty.http2.FlowControlStrategy;
|
||||||
import org.eclipse.jetty.http2.HTTP2Session;
|
import org.eclipse.jetty.http2.HTTP2Session;
|
||||||
import org.eclipse.jetty.http2.IStream;
|
import org.eclipse.jetty.http2.IStream;
|
||||||
|
import org.eclipse.jetty.http2.api.Session;
|
||||||
import org.eclipse.jetty.http2.api.Stream;
|
import org.eclipse.jetty.http2.api.Stream;
|
||||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||||
import org.eclipse.jetty.http2.frames.PushPromiseFrame;
|
import org.eclipse.jetty.http2.frames.PushPromiseFrame;
|
||||||
|
@ -35,7 +36,7 @@ public class HTTP2ClientSession extends HTTP2Session
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(HTTP2ClientSession.class);
|
private static final Logger LOG = Log.getLogger(HTTP2ClientSession.class);
|
||||||
|
|
||||||
public HTTP2ClientSession(Scheduler scheduler, EndPoint endPoint, Generator generator, Listener listener, FlowControlStrategy flowControl)
|
public HTTP2ClientSession(Scheduler scheduler, EndPoint endPoint, Generator generator, Session.Listener listener, FlowControlStrategy flowControl)
|
||||||
{
|
{
|
||||||
super(scheduler, endPoint, generator, listener, flowControl, 1);
|
super(scheduler, endPoint, generator, listener, flowControl, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,12 @@
|
||||||
<artifactId>http2-hpack</artifactId>
|
<artifactId>http2-hpack</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-jmx</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||||
<artifactId>jetty-test-helper</artifactId>
|
<artifactId>jetty-test-helper</artifactId>
|
||||||
|
@ -23,30 +29,30 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<bundle-symbolic-name>${project.groupId}.common</bundle-symbolic-name>
|
<bundle-symbolic-name>${project.groupId}.common</bundle-symbolic-name>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.felix</groupId>
|
<groupId>org.apache.felix</groupId>
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
<extensions>true</extensions>
|
<extensions>true</extensions>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>manifest</goal>
|
<goal>manifest</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<instructions>
|
<instructions>
|
||||||
<Export-Package>org.eclipse.jetty.http2.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";</Export-Package>
|
<Export-Package>org.eclipse.jetty.http2.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";</Export-Package>
|
||||||
</instructions>
|
</instructions>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -20,9 +20,12 @@ package org.eclipse.jetty.http2;
|
||||||
|
|
||||||
import org.eclipse.jetty.http2.api.Stream;
|
import org.eclipse.jetty.http2.api.Stream;
|
||||||
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
|
@ManagedObject
|
||||||
public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
||||||
{
|
{
|
||||||
protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class);
|
protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class);
|
||||||
|
@ -36,12 +39,14 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
||||||
this.initialStreamRecvWindow = DEFAULT_WINDOW_SIZE;
|
this.initialStreamRecvWindow = DEFAULT_WINDOW_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getInitialStreamSendWindow()
|
@ManagedAttribute(value = "The initial size of stream's flow control send window", readonly = true)
|
||||||
|
public int getInitialStreamSendWindow()
|
||||||
{
|
{
|
||||||
return initialStreamSendWindow;
|
return initialStreamSendWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getInitialStreamRecvWindow()
|
@ManagedAttribute(value = "The initial size of stream's flow control receive window", readonly = true)
|
||||||
|
public int getInitialStreamRecvWindow()
|
||||||
{
|
{
|
||||||
return initialStreamRecvWindow;
|
return initialStreamRecvWindow;
|
||||||
}
|
}
|
||||||
|
@ -102,6 +107,8 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
||||||
int oldSize = stream.updateSendWindow(delta);
|
int oldSize = stream.updateSendWindow(delta);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Updated stream send window {} -> {} for {}", oldSize, oldSize + delta, stream);
|
LOG.debug("Updated stream send window {} -> {} for {}", oldSize, oldSize + delta, stream);
|
||||||
|
if (oldSize <= 0)
|
||||||
|
onStreamUnstalled(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -109,6 +116,8 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
||||||
int oldSize = session.updateSendWindow(delta);
|
int oldSize = session.updateSendWindow(delta);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Updated session send window {} -> {} for {}", oldSize, oldSize + delta, session);
|
LOG.debug("Updated session send window {} -> {} for {}", oldSize, oldSize + delta, session);
|
||||||
|
if (oldSize <= 0)
|
||||||
|
onSessionUnstalled(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,4 +175,16 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Stream stalled {}", stream);
|
LOG.debug("Stream stalled {}", stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void onSessionUnstalled(ISession session)
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Session unstalled {}", session);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onStreamUnstalled(IStream stream)
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Stream unstalled {}", stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ import org.eclipse.jetty.http2.frames.Frame;
|
||||||
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
|
||||||
import org.eclipse.jetty.util.Atomics;
|
import org.eclipse.jetty.util.Atomics;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>A flow control strategy that accumulates updates and emits window control
|
* <p>A flow control strategy that accumulates updates and emits window control
|
||||||
|
@ -49,6 +51,7 @@ import org.eclipse.jetty.util.Callback;
|
||||||
* <p>The application consumes the remaining 15, so now SB=15, and no window
|
* <p>The application consumes the remaining 15, so now SB=15, and no window
|
||||||
* control frame is emitted.</p>
|
* control frame is emitted.</p>
|
||||||
*/
|
*/
|
||||||
|
@ManagedObject
|
||||||
public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
||||||
{
|
{
|
||||||
private final AtomicInteger maxSessionRecvWindow = new AtomicInteger(DEFAULT_WINDOW_SIZE);
|
private final AtomicInteger maxSessionRecvWindow = new AtomicInteger(DEFAULT_WINDOW_SIZE);
|
||||||
|
@ -67,6 +70,12 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
|
||||||
this.bufferRatio = bufferRatio;
|
this.bufferRatio = bufferRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The ratio between the receive buffer and the consume buffer")
|
||||||
|
public float getBufferRatio()
|
||||||
|
{
|
||||||
|
return bufferRatio;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStreamCreated(IStream stream)
|
public void onStreamCreated(IStream stream)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,11 +54,15 @@ import org.eclipse.jetty.util.Atomics;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.CountingCallback;
|
import org.eclipse.jetty.util.CountingCallback;
|
||||||
import org.eclipse.jetty.util.Promise;
|
import org.eclipse.jetty.util.Promise;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.util.thread.Scheduler;
|
import org.eclipse.jetty.util.thread.Scheduler;
|
||||||
|
|
||||||
public abstract class HTTP2Session implements ISession, Parser.Listener
|
@ManagedObject
|
||||||
|
public abstract class HTTP2Session extends ContainerLifeCycle implements ISession, Parser.Listener
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(HTTP2Session.class);
|
private static final Logger LOG = Log.getLogger(HTTP2Session.class);
|
||||||
|
|
||||||
|
@ -73,7 +77,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
|
||||||
private final Scheduler scheduler;
|
private final Scheduler scheduler;
|
||||||
private final EndPoint endPoint;
|
private final EndPoint endPoint;
|
||||||
private final Generator generator;
|
private final Generator generator;
|
||||||
private final Listener listener;
|
private final Session.Listener listener;
|
||||||
private final FlowControlStrategy flowControl;
|
private final FlowControlStrategy flowControl;
|
||||||
private final HTTP2Flusher flusher;
|
private final HTTP2Flusher flusher;
|
||||||
private int maxLocalStreams;
|
private int maxLocalStreams;
|
||||||
|
@ -81,7 +85,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
|
||||||
private long streamIdleTimeout;
|
private long streamIdleTimeout;
|
||||||
private boolean pushEnabled;
|
private boolean pushEnabled;
|
||||||
|
|
||||||
public HTTP2Session(Scheduler scheduler, EndPoint endPoint, Generator generator, Listener listener, FlowControlStrategy flowControl, int initialStreamId)
|
public HTTP2Session(Scheduler scheduler, EndPoint endPoint, Generator generator, Session.Listener listener, FlowControlStrategy flowControl, int initialStreamId)
|
||||||
{
|
{
|
||||||
this.scheduler = scheduler;
|
this.scheduler = scheduler;
|
||||||
this.endPoint = endPoint;
|
this.endPoint = endPoint;
|
||||||
|
@ -98,6 +102,14 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
|
||||||
this.pushEnabled = true; // SPEC: by default, push is enabled.
|
this.pushEnabled = true; // SPEC: by default, push is enabled.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doStart() throws Exception
|
||||||
|
{
|
||||||
|
addBean(flowControl);
|
||||||
|
super.doStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value = "The flow control strategy", readonly = true)
|
||||||
public FlowControlStrategy getFlowControlStrategy()
|
public FlowControlStrategy getFlowControlStrategy()
|
||||||
{
|
{
|
||||||
return flowControl;
|
return flowControl;
|
||||||
|
@ -123,6 +135,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
|
||||||
this.maxRemoteStreams = maxRemoteStreams;
|
this.maxRemoteStreams = maxRemoteStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The stream's idle timeout")
|
||||||
public long getStreamIdleTimeout()
|
public long getStreamIdleTimeout()
|
||||||
{
|
{
|
||||||
return streamIdleTimeout;
|
return streamIdleTimeout;
|
||||||
|
@ -709,17 +722,25 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The number of active streams")
|
||||||
|
public int getStreamCount()
|
||||||
|
{
|
||||||
|
return streams.size();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IStream getStream(int streamId)
|
public IStream getStream(int streamId)
|
||||||
{
|
{
|
||||||
return streams.get(streamId);
|
return streams.get(streamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value = "The flow control send window", readonly = true)
|
||||||
public int getSendWindow()
|
public int getSendWindow()
|
||||||
{
|
{
|
||||||
return sendWindow.get();
|
return sendWindow.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value = "The flow control receive window", readonly = true)
|
||||||
public int getRecvWindow()
|
public int getRecvWindow()
|
||||||
{
|
{
|
||||||
return recvWindow.get();
|
return recvWindow.get();
|
||||||
|
@ -753,6 +774,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ManagedAttribute(value = "Whether HTTP/2 push is enabled", readonly = true)
|
||||||
public boolean isPushEnabled()
|
public boolean isPushEnabled()
|
||||||
{
|
{
|
||||||
return pushEnabled;
|
return pushEnabled;
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.http2.client.http;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory;
|
import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory;
|
||||||
|
@ -71,6 +72,7 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements
|
||||||
client.setByteBufferPool(httpClient.getByteBufferPool());
|
client.setByteBufferPool(httpClient.getByteBufferPool());
|
||||||
client.setConnectTimeout(httpClient.getConnectTimeout());
|
client.setConnectTimeout(httpClient.getConnectTimeout());
|
||||||
client.setIdleTimeout(httpClient.getIdleTimeout());
|
client.setIdleTimeout(httpClient.getIdleTimeout());
|
||||||
|
client.setInputBufferSize(httpClient.getResponseBufferSize());
|
||||||
}
|
}
|
||||||
addBean(client);
|
addBean(client);
|
||||||
super.doStart();
|
super.doStart();
|
||||||
|
@ -160,6 +162,14 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements
|
||||||
promise.failed(failure);
|
promise.failed(failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Integer, Integer> onPreface(Session session)
|
||||||
|
{
|
||||||
|
Map<Integer, Integer> settings = new HashMap<>();
|
||||||
|
settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, client.getInitialStreamRecvWindow());
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSettings(Session session, SettingsFrame frame)
|
public void onSettings(Session session, SettingsFrame frame)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,15 +31,21 @@ import org.eclipse.jetty.io.EndPoint;
|
||||||
import org.eclipse.jetty.server.AbstractConnectionFactory;
|
import org.eclipse.jetty.server.AbstractConnectionFactory;
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
import org.eclipse.jetty.server.HttpConfiguration;
|
import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.annotation.Name;
|
import org.eclipse.jetty.util.annotation.Name;
|
||||||
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
|
|
||||||
|
@ManagedObject
|
||||||
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
|
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
|
||||||
{
|
{
|
||||||
|
private final Connection.Listener connectionListener = new ConnectionListener();
|
||||||
|
private final HttpConfiguration httpConfiguration;
|
||||||
private int maxDynamicTableSize = 4096;
|
private int maxDynamicTableSize = 4096;
|
||||||
private int initialStreamSendWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
|
private int initialStreamSendWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
|
||||||
private int maxConcurrentStreams = -1;
|
private int maxConcurrentStreams = -1;
|
||||||
private int maxHeaderBlockFragment = 0;
|
private int maxHeaderBlockFragment = 0;
|
||||||
private final HttpConfiguration httpConfiguration;
|
|
||||||
|
|
||||||
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
|
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
|
||||||
{
|
{
|
||||||
|
@ -50,8 +56,10 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
||||||
{
|
{
|
||||||
super(protocols);
|
super(protocols);
|
||||||
this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
|
this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
|
||||||
|
addBean(httpConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The HPACK dynamic table maximum size")
|
||||||
public int getMaxDynamicTableSize()
|
public int getMaxDynamicTableSize()
|
||||||
{
|
{
|
||||||
return maxDynamicTableSize;
|
return maxDynamicTableSize;
|
||||||
|
@ -62,6 +70,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
||||||
this.maxDynamicTableSize = maxDynamicTableSize;
|
this.maxDynamicTableSize = maxDynamicTableSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The initial size of stream's flow control send window")
|
||||||
public int getInitialStreamSendWindow()
|
public int getInitialStreamSendWindow()
|
||||||
{
|
{
|
||||||
return initialStreamSendWindow;
|
return initialStreamSendWindow;
|
||||||
|
@ -72,6 +81,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
||||||
this.initialStreamSendWindow = initialStreamSendWindow;
|
this.initialStreamSendWindow = initialStreamSendWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The max number of concurrent streams per session")
|
||||||
public int getMaxConcurrentStreams()
|
public int getMaxConcurrentStreams()
|
||||||
{
|
{
|
||||||
return maxConcurrentStreams;
|
return maxConcurrentStreams;
|
||||||
|
@ -116,7 +126,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
||||||
ServerParser parser = newServerParser(connector, session);
|
ServerParser parser = newServerParser(connector, session);
|
||||||
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
|
||||||
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
|
||||||
|
connection.addListener(connectionListener);
|
||||||
return configure(connection, connector, endPoint);
|
return configure(connection, connector, endPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,4 +141,19 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
||||||
{
|
{
|
||||||
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
|
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ConnectionListener extends ContainerLifeCycle implements Connection.Listener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onOpened(Connection connection)
|
||||||
|
{
|
||||||
|
addManaged((LifeCycle)((HTTP2Connection)connection).getSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClosed(Connection connection)
|
||||||
|
{
|
||||||
|
removeBean(((HTTP2Connection)connection).getSession());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,22 +26,25 @@ import org.eclipse.jetty.io.AbstractConnection;
|
||||||
import org.eclipse.jetty.io.Connection;
|
import org.eclipse.jetty.io.Connection;
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
import org.eclipse.jetty.io.EndPoint;
|
||||||
import org.eclipse.jetty.util.ArrayUtil;
|
import org.eclipse.jetty.util.ArrayUtil;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
/**
|
||||||
* Abstract ConnectionFactory
|
* <p>Provides the common handling for {@link ConnectionFactory} implementations including:</p>
|
||||||
* <p>Provides the common handling for {@link ConnectionFactory} implementations including:<ul>
|
* <ul>
|
||||||
* <li>Protocol identification
|
* <li>Protocol identification</li>
|
||||||
* <li>Configuration of new Connections:<ul>
|
* <li>Configuration of new Connections:
|
||||||
* <li>Setting inputbuffer size
|
* <ul>
|
||||||
* <li>Calling {@link Connection#addListener(Connection.Listener)} for all
|
* <li>Setting inputbuffer size</li>
|
||||||
* Connection.Listener instances found as beans on the {@link Connector} and this {@link ConnectionFactory}
|
* <li>Calling {@link Connection#addListener(Connection.Listener)} for all
|
||||||
* </ul>
|
* Connection.Listener instances found as beans on the {@link Connector}
|
||||||
|
* and this {@link ConnectionFactory}</li>
|
||||||
|
* </ul>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
|
@ManagedObject
|
||||||
public abstract class AbstractConnectionFactory extends ContainerLifeCycle implements ConnectionFactory
|
public abstract class AbstractConnectionFactory extends ContainerLifeCycle implements ConnectionFactory
|
||||||
{
|
{
|
||||||
private final String _protocol;
|
private final String _protocol;
|
||||||
|
@ -53,7 +56,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
|
||||||
_protocol=protocol;
|
_protocol=protocol;
|
||||||
_protocols=Collections.unmodifiableList(Arrays.asList(new String[]{protocol}));
|
_protocols=Collections.unmodifiableList(Arrays.asList(new String[]{protocol}));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractConnectionFactory(String... protocols)
|
protected AbstractConnectionFactory(String... protocols)
|
||||||
{
|
{
|
||||||
_protocol=protocols[0];
|
_protocol=protocols[0];
|
||||||
|
@ -61,6 +64,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ManagedAttribute(value = "The protocol name", readonly = true)
|
||||||
public String getProtocol()
|
public String getProtocol()
|
||||||
{
|
{
|
||||||
return _protocol;
|
return _protocol;
|
||||||
|
@ -72,6 +76,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
|
||||||
return _protocols;
|
return _protocols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute("The buffer size used to read from the network")
|
||||||
public int getInputBufferSize()
|
public int getInputBufferSize()
|
||||||
{
|
{
|
||||||
return _inputbufferSize;
|
return _inputbufferSize;
|
||||||
|
@ -96,7 +101,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
|
||||||
// Add Connection.Listeners from this factory
|
// Add Connection.Listeners from this factory
|
||||||
for (Connection.Listener listener : getBeans(Connection.Listener.class))
|
for (Connection.Listener listener : getBeans(Connection.Listener.class))
|
||||||
connection.addListener(listener);
|
connection.addListener(listener);
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue