Fixes #9720 - Http2Session.streamIdleTimeout should permit being disabled
Now allowing to specify a negative value for AbstractHTTP2ServerConnectionFactory.streamIdleTimeout, while 0 implies to use the default value (from the EndPoint). Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
87c24e7258
commit
afef05a413
|
@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.FlowControlStrategy;
|
||||
|
@ -676,6 +677,78 @@ public class IdleTimeoutTest extends AbstractTest
|
|||
assertThat(((ISession)client).updateSendWindow(0), Matchers.greaterThan(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableStreamIdleTimeout() throws Exception
|
||||
{
|
||||
// Set the stream idle timeout to a negative value to disable it.
|
||||
long streamIdleTimeout = -1;
|
||||
start(new ServerSessionListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
return new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onData(Stream stream, DataFrame frame, Callback callback)
|
||||
{
|
||||
callback.succeeded();
|
||||
if (frame.isEndStream())
|
||||
{
|
||||
MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY);
|
||||
stream.headers(new HeadersFrame(stream.getId(), response, null, true));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}, h2 -> h2.setStreamIdleTimeout(streamIdleTimeout));
|
||||
connector.setIdleTimeout(idleTimeout);
|
||||
|
||||
CountDownLatch responseLatch = new CountDownLatch(2);
|
||||
CountDownLatch resetLatch = new CountDownLatch(1);
|
||||
Session session = newClient(new Session.Listener.Adapter());
|
||||
MetaData.Request metaData1 = newRequest("GET", "/1", HttpFields.EMPTY);
|
||||
Stream stream1 = session.newStream(new HeadersFrame(metaData1, null, false), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
responseLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReset(Stream stream, ResetFrame frame)
|
||||
{
|
||||
resetLatch.countDown();
|
||||
}
|
||||
}).get(5, TimeUnit.SECONDS);
|
||||
|
||||
MetaData.Request metaData2 = newRequest("GET", "/2", HttpFields.EMPTY);
|
||||
Stream stream2 = session.newStream(new HeadersFrame(metaData2, null, false), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
responseLatch.countDown();
|
||||
}
|
||||
}).get(5, TimeUnit.SECONDS);
|
||||
// Keep the connection busy with the stream2, stream1 must not idle timeout.
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
Thread.sleep(idleTimeout / 2);
|
||||
stream2.data(new DataFrame(stream2.getId(), ByteBuffer.allocate(64), false));
|
||||
}
|
||||
|
||||
// Stream1 must not have idle timed out.
|
||||
assertFalse(resetLatch.await(idleTimeout / 2, TimeUnit.MILLISECONDS));
|
||||
|
||||
// Finish the streams.
|
||||
stream1.data(new DataFrame(stream1.getId(), ByteBuffer.allocate(128), true));
|
||||
stream2.data(new DataFrame(stream2.getId(), ByteBuffer.allocate(64), true));
|
||||
|
||||
assertTrue(responseLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private void sleep(long value)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -122,7 +122,6 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
this.maxLocalStreams = -1;
|
||||
this.maxRemoteStreams = -1;
|
||||
this.localStreamIds.set(initialStreamId);
|
||||
this.streamIdleTimeout = endPoint.getIdleTimeout();
|
||||
this.sendWindow.set(FlowControlStrategy.DEFAULT_WINDOW_SIZE);
|
||||
this.recvWindow.set(FlowControlStrategy.DEFAULT_WINDOW_SIZE);
|
||||
this.writeThreshold = 32 * 1024;
|
||||
|
|
|
@ -198,6 +198,15 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
return streamIdleTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the HTTP/2 stream idle timeout.</p>
|
||||
* <p>Value {@code -1} disables the idle timeout,
|
||||
* value {@code 0} implies using the default idle timeout,
|
||||
* positive values specify the idle timeout in milliseconds.</p>
|
||||
*
|
||||
* @param streamIdleTimeout the idle timeout in milliseconds,
|
||||
* {@code 0} for the default, {@code -1} to disable the idle timeout
|
||||
*/
|
||||
public void setStreamIdleTimeout(long streamIdleTimeout)
|
||||
{
|
||||
this.streamIdleTimeout = streamIdleTimeout;
|
||||
|
@ -331,8 +340,9 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
// the typical case is that the connection will be busier and the
|
||||
// stream idle timeout will expire earlier than the connection's.
|
||||
long streamIdleTimeout = getStreamIdleTimeout();
|
||||
if (streamIdleTimeout > 0)
|
||||
session.setStreamIdleTimeout(streamIdleTimeout);
|
||||
if (streamIdleTimeout == 0)
|
||||
streamIdleTimeout = endPoint.getIdleTimeout();
|
||||
session.setStreamIdleTimeout(streamIdleTimeout);
|
||||
session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
|
||||
session.setWriteThreshold(getHttpConfiguration().getOutputBufferSize());
|
||||
session.setConnectProtocolEnabled(isConnectProtocolEnabled());
|
||||
|
|
Loading…
Reference in New Issue