@@ -144,6 +144,11 @@ enum SettingsHandshake { READY, TRANSMITTED, ACKED }
144144 private final Map <Integer , PriorityValue > priorities = new ConcurrentHashMap <>();
145145 private volatile boolean peerNoRfc7540Priorities ;
146146
147+
148+ private static final long STREAM_TIMEOUT_GRANULARITY_MILLIS = 1000 ;
149+ private long lastStreamTimeoutCheckMillis ;
150+
151+
147152 AbstractH2StreamMultiplexer (
148153 final ProtocolIOSession ioSession ,
149154 final FrameFactory frameFactory ,
@@ -439,10 +444,6 @@ public final void onInput(final ByteBuffer src) throws HttpException, IOExceptio
439444 for (;;) {
440445 final RawFrame frame = inputBuffer .read (src , ioSession );
441446 if (frame != null ) {
442- if (connState .compareTo (ConnectionHandshake .SHUTDOWN ) < 0 ) {
443- checkStreamTimeouts (System .nanoTime ());
444- }
445-
446447 if (streamListener != null ) {
447448 streamListener .onFrameInput (this , frame .getStreamId (), frame );
448449 }
@@ -460,7 +461,7 @@ public final void onInput(final ByteBuffer src) throws HttpException, IOExceptio
460461 }
461462 }
462463 if (connState .compareTo (ConnectionHandshake .SHUTDOWN ) < 0 ) {
463- checkStreamTimeouts ( System . nanoTime () );
464+ validateStreamTimeouts ( );
464465 }
465466 }
466467 }
@@ -541,7 +542,7 @@ public final void onOutput() throws HttpException, IOException {
541542 }
542543
543544 if (connState .compareTo (ConnectionHandshake .SHUTDOWN ) < 0 ) {
544- checkStreamTimeouts ( System . nanoTime () );
545+ validateStreamTimeouts ( );
545546 }
546547
547548 if (connState .compareTo (ConnectionHandshake .GRACEFUL_SHUTDOWN ) == 0 ) {
@@ -655,7 +656,6 @@ private void executeRequest(final RequestExecutionCommand requestExecutionComman
655656 requestExecutionCommand .getExchangeHandler (),
656657 requestExecutionCommand .getPushHandlerFactory (),
657658 requestExecutionCommand .getContext ()));
658- initializeStreamTimeouts (stream );
659659
660660 if (streamListener != null ) {
661661 final int initInputWindow = stream .getInputWindow ().get ();
@@ -774,12 +774,10 @@ private void consumeFrame(final RawFrame frame) throws HttpException, IOExceptio
774774 final H2StreamChannel channel = createChannel (streamId );
775775 if (connState .compareTo (ConnectionHandshake .ACTIVE ) <= 0 ) {
776776 stream = streams .createActive (channel , incomingRequest (channel ));
777- initializeStreamTimeouts (stream );
778777 streams .resetIfExceedsMaxConcurrentLimit (stream , localConfig .getMaxConcurrentStreams ());
779778 } else {
780779 channel .localReset (H2Error .REFUSED_STREAM );
781780 stream = streams .createActive (channel , NoopH2StreamHandler .INSTANCE );
782- initializeStreamTimeouts (stream );
783781 }
784782 } else if (stream .isLocalClosed () && stream .isRemoteClosed ()) {
785783 throw new H2ConnectionException (H2Error .STREAM_CLOSED , "Stream closed" );
@@ -970,7 +968,6 @@ private void consumeFrame(final RawFrame frame) throws HttpException, IOExceptio
970968 channel .localReset (H2Error .REFUSED_STREAM );
971969 promisedStream = streams .createActive (channel , NoopH2StreamHandler .INSTANCE );
972970 }
973- initializeStreamTimeouts (promisedStream );
974971 try {
975972 consumePushPromiseFrame (frame , payload , promisedStream );
976973 } catch (final H2StreamResetException ex ) {
@@ -1376,16 +1373,8 @@ H2StreamChannel createChannel(final int streamId) {
13761373 return new H2StreamChannelImpl (streamId , initInputWinSize , initOutputWinSize );
13771374 }
13781375
1379- private void initializeStreamTimeouts (final H2Stream stream ) {
1380- final Timeout socketTimeout = ioSession .getSocketTimeout ();
1381- if (socketTimeout != null && socketTimeout .isEnabled ()) {
1382- stream .setIdleTimeout (socketTimeout );
1383- }
1384- }
1385-
13861376 H2Stream createStream (final H2StreamChannel channel , final H2StreamHandler streamHandler ) {
13871377 final H2Stream stream = streams .createActive (channel , streamHandler );
1388- initializeStreamTimeouts (stream );
13891378 return stream ;
13901379 }
13911380
@@ -1489,7 +1478,6 @@ public void push(final List<Header> headers, final AsyncPushProducer pushProduce
14891478 final int promisedStreamId = streams .generateStreamId ();
14901479 final H2StreamChannel channel = createChannel (promisedStreamId );
14911480 final H2Stream stream = streams .createReserved (channel , outgoingPushPromise (channel , pushProducer ));
1492- initializeStreamTimeouts (stream );
14931481
14941482 commitPushPromise (id , promisedStreamId , headers );
14951483 stream .markRemoteClosed ();
@@ -1614,42 +1602,29 @@ private void checkStreamTimeouts(final long nowNanos) throws IOException {
16141602 }
16151603
16161604 final Timeout idleTimeout = stream .getIdleTimeout ();
1617- final Timeout lifetimeTimeout = stream .getLifetimeTimeout ();
1618- if ((idleTimeout == null || !idleTimeout .isEnabled ())
1619- && (lifetimeTimeout == null || !lifetimeTimeout .isEnabled ())) {
1605+ if (idleTimeout == null || !idleTimeout .isEnabled ()) {
16201606 continue ;
16211607 }
16221608
1623- final long created = stream .getCreatedNanos ();
16241609 final long last = stream .getLastActivityNanos ();
1625-
1626- if (idleTimeout != null && idleTimeout .isEnabled ()) {
1627- final long idleNanos = idleTimeout .toNanoseconds ();
1628- if (idleNanos > 0 && nowNanos - last > idleNanos ) {
1629- final int streamId = stream .getId ();
1630- final H2StreamTimeoutException ex = new H2StreamTimeoutException (
1631- "HTTP/2 stream idle timeout (" + idleTimeout + ")" ,
1632- streamId ,
1633- idleTimeout ,
1634- true );
1635- stream .localReset (ex , H2Error .CANCEL );
1636- // Once reset due to idle timeout, we do not care about lifetime anymore
1637- continue ;
1638- }
1610+ final long idleNanos = idleTimeout .toNanoseconds ();
1611+ if (idleNanos > 0 && nowNanos - last > idleNanos ) {
1612+ final int streamId = stream .getId ();
1613+ final H2StreamTimeoutException ex = new H2StreamTimeoutException (
1614+ "HTTP/2 stream idle timeout (" + idleTimeout + ")" ,
1615+ streamId ,
1616+ idleTimeout ,
1617+ true );
1618+ stream .localReset (ex , H2Error .CANCEL );
16391619 }
1620+ }
1621+ }
16401622
1641- if (lifetimeTimeout != null && lifetimeTimeout .isEnabled ()) {
1642- final long lifeNanos = lifetimeTimeout .toNanoseconds ();
1643- if (lifeNanos > 0 && nowNanos - created > lifeNanos ) {
1644- final int streamId = stream .getId ();
1645- final H2StreamTimeoutException ex = new H2StreamTimeoutException (
1646- "HTTP/2 stream lifetime timeout (" + lifetimeTimeout + ")" ,
1647- streamId ,
1648- lifetimeTimeout ,
1649- false );
1650- stream .localReset (ex , H2Error .CANCEL );
1651- }
1652- }
1623+ private void validateStreamTimeouts () throws IOException {
1624+ final long nowMillis = System .currentTimeMillis ();
1625+ if ((nowMillis - lastStreamTimeoutCheckMillis ) >= STREAM_TIMEOUT_GRANULARITY_MILLIS ) {
1626+ lastStreamTimeoutCheckMillis = nowMillis ;
1627+ checkStreamTimeouts (System .nanoTime ());
16531628 }
16541629 }
16551630
0 commit comments