in httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java [452:542]
public final void onOutput() throws HttpException, IOException {
ioSession.getLock().lock();
try {
if (!outputBuffer.isEmpty()) {
outputBuffer.flush(ioSession);
}
while (outputBuffer.isEmpty()) {
final RawFrame frame = outputQueue.poll();
if (frame != null) {
if (streamListener != null) {
streamListener.onFrameOutput(this, frame.getStreamId(), frame);
}
outputBuffer.write(frame, ioSession);
} else {
break;
}
}
} finally {
ioSession.getLock().unlock();
}
if (connState.compareTo(ConnectionHandshake.SHUTDOWN) < 0) {
if (connOutputWindow.get() > 0 && remoteSettingState == SettingsHandshake.ACKED) {
produceOutput();
}
final int pendingOutputRequests = outputRequests.get();
boolean outputPending = false;
if (!streamMap.isEmpty() && connOutputWindow.get() > 0) {
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
final Map.Entry<Integer, H2Stream> entry = it.next();
final H2Stream stream = entry.getValue();
if (!stream.isLocalClosed()
&& stream.getOutputWindow().get() > 0
&& stream.isOutputReady()) {
outputPending = true;
break;
}
}
}
ioSession.getLock().lock();
try {
if (!outputPending && outputBuffer.isEmpty() && outputQueue.isEmpty()
&& outputRequests.compareAndSet(pendingOutputRequests, 0)) {
ioSession.clearEvent(SelectionKey.OP_WRITE);
} else {
outputRequests.addAndGet(-pendingOutputRequests);
}
} finally {
ioSession.getLock().unlock();
}
}
if (connState.compareTo(ConnectionHandshake.ACTIVE) <= 0 && remoteSettingState == SettingsHandshake.ACKED) {
processPendingCommands();
}
if (connState.compareTo(ConnectionHandshake.GRACEFUL_SHUTDOWN) == 0) {
int liveStreams = 0;
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
final Map.Entry<Integer, H2Stream> entry = it.next();
final H2Stream stream = entry.getValue();
if (stream.isLocalClosed() && stream.isRemoteClosed()) {
stream.releaseResources();
it.remove();
} else {
if (idGenerator.isSameSide(stream.getId()) || stream.getId() <= processedRemoteStreamId) {
liveStreams++;
}
}
}
if (liveStreams == 0) {
connState = ConnectionHandshake.SHUTDOWN;
}
}
if (connState.compareTo(ConnectionHandshake.SHUTDOWN) >= 0) {
if (!streamMap.isEmpty()) {
for (final H2Stream stream : streamMap.values()) {
stream.releaseResources();
}
streamMap.clear();
}
ioSession.getLock().lock();
try {
if (outputBuffer.isEmpty() && outputQueue.isEmpty()) {
ioSession.close();
}
} finally {
ioSession.getLock().unlock();
}
}
}