@@ -364,7 +364,8 @@ class Http2Stream internal constructor(
364364
365365 val unacknowledgedBytesRead = readBytesTotal - readBytesAcknowledged
366366 if (errorExceptionToDeliver == null &&
367- unacknowledgedBytesRead >= connection.okHttpSettings.initialWindowSize / 2 ) {
367+ unacknowledgedBytesRead >= connection.okHttpSettings.initialWindowSize / 2
368+ ) {
368369 // Flow control: notify the peer that we're ready for more data! Only send a
369370 // WINDOW_UPDATE if the stream isn't in error.
370371 connection.writeWindowUpdateLater(id, unacknowledgedBytesRead)
@@ -387,8 +388,6 @@ class Http2Stream internal constructor(
387388 }
388389
389390 if (readBytesDelivered != - 1L ) {
390- // Update connection.unacknowledgedBytesRead outside the synchronized block.
391- updateConnectionFlowControl(readBytesDelivered)
392391 return readBytesDelivered
393392 }
394393
@@ -418,41 +417,39 @@ class Http2Stream internal constructor(
418417 internal fun receive (source : BufferedSource , byteCount : Long ) {
419418 this @Http2Stream.assertThreadDoesntHoldLock()
420419
421- var byteCount = byteCount
420+ var remainingByteCount = byteCount
422421
423- while (byteCount > 0L ) {
422+ while (remainingByteCount > 0L ) {
424423 val finished: Boolean
425424 val flowControlError: Boolean
426425 synchronized(this @Http2Stream) {
427426 finished = this .finished
428- flowControlError = byteCount + readBuffer.size > maxByteCount
427+ flowControlError = remainingByteCount + readBuffer.size > maxByteCount
429428 }
430429
431430 // If the peer sends more data than we can handle, discard it and close the connection.
432431 if (flowControlError) {
433- source.skip(byteCount )
432+ source.skip(remainingByteCount )
434433 closeLater(ErrorCode .FLOW_CONTROL_ERROR )
435434 return
436435 }
437436
438437 // Discard data received after the stream is finished. It's probably a benign race.
439438 if (finished) {
440- source.skip(byteCount )
439+ source.skip(remainingByteCount )
441440 return
442441 }
443442
444443 // Fill the receive buffer without holding any locks.
445- val read = source.read(receiveBuffer, byteCount )
444+ val read = source.read(receiveBuffer, remainingByteCount )
446445 if (read == - 1L ) throw EOFException ()
447- byteCount - = read
446+ remainingByteCount - = read
448447
449448 // Move the received data to the read buffer to the reader can read it. If this source has
450449 // been closed since this read began we must discard the incoming data and tell the
451450 // connection we've done so.
452- var bytesDiscarded = 0L
453451 synchronized(this @Http2Stream) {
454452 if (closed) {
455- bytesDiscarded = receiveBuffer.size
456453 receiveBuffer.clear()
457454 } else {
458455 val wasEmpty = readBuffer.size == 0L
@@ -462,10 +459,13 @@ class Http2Stream internal constructor(
462459 }
463460 }
464461 }
465- if (bytesDiscarded > 0L ) {
466- updateConnectionFlowControl(bytesDiscarded)
467- }
468462 }
463+
464+ // Update the connection flow control, as this is a shared resource.
465+ // Even if our stream doesn't need more data, others might.
466+ // But delay updating the stream flow control until that stream has been
467+ // consumed
468+ updateConnectionFlowControl(byteCount)
469469 }
470470
471471 override fun timeout (): Timeout = readTimeout
0 commit comments