@@ -1225,6 +1225,7 @@ private StreamHolder handleRstStream(int streamId, boolean receivedRst) {
1225
1225
resetStreamTracker .store (streamId , holder );
1226
1226
if (streamId % 2 == (isClient () ? 1 : 0 )) {
1227
1227
sendConcurrentStreamsAtomicUpdater .getAndDecrement (this );
1228
+ holder .sent = true ;
1228
1229
} else {
1229
1230
receiveConcurrentStreamsAtomicUpdater .getAndDecrement (this );
1230
1231
}
@@ -1239,13 +1240,14 @@ private StreamHolder handleRstStream(int streamId, boolean receivedRst) {
1239
1240
//Server side originated, no input from client other than RST
1240
1241
//this can happen on page refresh when push happens, but client
1241
1242
//still has valid cache entry
1243
+ //NOTE: this is specific case when its set.
1242
1244
holder .resetByPeer = receivedRst ;
1243
1245
} else {
1244
1246
handleRstWindow ();
1245
1247
}
1246
1248
}
1247
1249
} else if (receivedRst ){
1248
- final StreamHolder resetStream = resetStreamTracker .find (streamId );
1250
+ final StreamHolder resetStream = resetStreamTracker .find (streamId , true );
1249
1251
if (resetStream != null && resetStream .resetByPeer ) {
1250
1252
//This means other side reset stream at some point.
1251
1253
//depending on peer or network latency our frames might be late and
@@ -1378,6 +1380,10 @@ private static final class StreamHolder {
1378
1380
* This flag is set only in case of short lived server push that was reset by remote end.
1379
1381
*/
1380
1382
boolean resetByPeer = false ;
1383
+ /**
1384
+ * flag indicate whether our side originated. This is done for caching purposes, handlng differs.
1385
+ */
1386
+ boolean sent = false ;
1381
1387
Http2StreamSourceChannel sourceChannel ;
1382
1388
Http2StreamSinkChannel sinkChannel ;
1383
1389
@@ -1388,6 +1394,13 @@ private static final class StreamHolder {
1388
1394
StreamHolder (Http2StreamSinkChannel sinkChannel ) {
1389
1395
this .sinkChannel = sinkChannel ;
1390
1396
}
1397
+
1398
+ @ Override
1399
+ public String toString () {
1400
+ return "StreamHolder [sourceClosed=" + sourceClosed + ", sinkClosed=" + sinkClosed + ", resetByPeer=" + resetByPeer
1401
+ + ", sent=" + sent + ", sourceChannel=" + sourceChannel + ", sinkChannel=" + sinkChannel + "]" ;
1402
+ }
1403
+
1391
1404
}
1392
1405
1393
1406
// cache that keeps track of streams until they can be evicted @see Http2Channel#RST_STREAM_EVICATION_TIME
@@ -1403,12 +1416,27 @@ private void store(int streamId, StreamHolder streamHolder) {
1403
1416
streamHolders .put (streamId , streamHolder );
1404
1417
entries .add (new StreamCacheEntry (streamId ));
1405
1418
}
1406
- private StreamHolder find (int streamId ) {
1419
+
1420
+ /**
1421
+ * Method will return only sent
1422
+ * @param streamId
1423
+ * @return
1424
+ */
1425
+ private StreamHolder find (final int streamId ) {
1426
+ return find (streamId , false );
1427
+ }
1428
+
1429
+ private StreamHolder find (final int streamId , final boolean all ) {
1407
1430
for (Iterator <StreamCacheEntry > iterator = entries .iterator (); iterator .hasNext ();) {
1408
1431
StreamCacheEntry entry = iterator .next ();
1409
1432
if (entry .shouldEvict ()) {
1410
1433
iterator .remove ();
1411
1434
StreamHolder holder = streamHolders .remove (entry .streamId );
1435
+ if (!holder .sent || holder .resetByPeer ) {
1436
+ //if its not our end of chain, its just cached, so we only cache for purpose of
1437
+ // handling eager RST
1438
+ continue ;
1439
+ }
1412
1440
AbstractHttp2StreamSourceChannel receiver = holder .sourceChannel ;
1413
1441
if (receiver != null ) {
1414
1442
IoUtils .safeClose (receiver );
@@ -1422,7 +1450,12 @@ private StreamHolder find(int streamId) {
1422
1450
}
1423
1451
} else break ;
1424
1452
}
1425
- return streamHolders .get (streamId );
1453
+ final StreamHolder holder = streamHolders .get (streamId );
1454
+ if (holder != null && (!all && !holder .sent )) {
1455
+ return null ;
1456
+ } else {
1457
+ return holder ;
1458
+ }
1426
1459
}
1427
1460
1428
1461
private Map <Integer , StreamHolder > getStreamHolders () {
0 commit comments