Skip to content

Commit

Permalink
[UNDERTOW-2034] At Http2StreamSinkChannel.awaitWritable, wait for flo…
Browse files Browse the repository at this point in the history
…w control window update if there is timeout available before throwing no window update IOException
  • Loading branch information
fl4via committed Jun 10, 2022
1 parent 4d5f6e1 commit bf39a3a
Showing 1 changed file with 23 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package io.undertow.protocols.http2;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;

import io.undertow.UndertowMessages;
Expand All @@ -27,7 +28,10 @@
import org.xnio.IoUtils;

/**
* Stream sink channel used for HTTP2 communication.
*
* @author Stuart Douglas
* @author Flavia Rainone
*/
public abstract class Http2StreamSinkChannel extends AbstractHttp2StreamSinkChannel {

Expand Down Expand Up @@ -118,8 +122,11 @@ protected int grabFlowControlBytes(int toSend) {
int newWindowSize = this.getChannel().getInitialSendWindowSize();
int settingsDelta = newWindowSize - this.initialWindowSize;
//first adjust for any settings frame updates
this.initialWindowSize = newWindowSize;
this.flowControlWindow += settingsDelta;
if (settingsDelta != 0) {
this.initialWindowSize = newWindowSize;
this.flowControlWindow += settingsDelta;
flowControlLock.notifyAll();
}

int min = Math.min(toSend, this.flowControlWindow);
int actualBytes = this.getChannel().grabFlowControlBytes(min);
Expand All @@ -140,6 +147,7 @@ void updateFlowControlWindow(final int delta) throws IOException {
return;
}
flowControlWindow += delta;
flowControlLock.notifyAll();
}
if (exhausted) {
getChannel().notifyFlowControlAllowed();
Expand Down Expand Up @@ -183,9 +191,22 @@ public void awaitWritable() throws IOException {
synchronized (flowControlLock) {
flowControlWindow = this.flowControlWindow;
}
long initialTime = System.nanoTime();
super.awaitWritable();
synchronized (flowControlLock) {
if (isReadyForFlush() && flowControlWindow <= 0 && flowControlWindow == this.flowControlWindow) {
final long timeout = getAwaitWritableTimeout();
long remainingTimeout;
while ((remainingTimeout = timeout * 1_000_000 - (System.nanoTime() - initialTime)) > 0) {
try {
flowControlLock.wait(remainingTimeout/ 1_000_000, (int) (remainingTimeout % 1_000_000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new InterruptedIOException();
}
if (flowControlWindow != this.flowControlWindow)
return;
}
throw UndertowMessages.MESSAGES.noWindowUpdate(getAwaitWritableTimeout());
}
}
Expand Down

0 comments on commit bf39a3a

Please # to comment.