package io.undertow.protocols.http2;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import io.undertow.UndertowLogger;
import io.undertow.server.protocol.framed.FramePriority;
import io.undertow.server.protocol.framed.SendFrameHeader;
class Http2FramePriority implements FramePriority<Http2Channel, AbstractHttp2StreamSourceChannel, AbstractHttp2StreamSinkChannel> {
private int nextId;
Http2FramePriority(int nextId) {
this.nextId = nextId;
}
@Override
public boolean insertFrame(AbstractHttp2StreamSinkChannel newFrame, List<AbstractHttp2StreamSinkChannel> pendingFrames) {
boolean incrementIfAccepted = false;
if ((newFrame.getChannel().isClient() && newFrame instanceof Http2HeadersStreamSinkChannel) ||
newFrame instanceof Http2PushPromiseStreamSinkChannel) {
if (newFrame instanceof Http2PushPromiseStreamSinkChannel) {
int streamId = ((Http2PushPromiseStreamSinkChannel) newFrame).getStreamId();
if (streamId > nextId) {
return false;
} else if (streamId == nextId) {
incrementIfAccepted = true;
}
} else {
int streamId = ((Http2HeadersStreamSinkChannel) newFrame).getStreamId();
if (streamId > nextId) {
return false;
} else if (streamId == nextId) {
incrementIfAccepted = true;
}
}
}
if (newFrame instanceof Http2StreamSinkChannel) {
if (newFrame.isBroken() || !newFrame.isOpen()) {
return true;
}
try {
SendFrameHeader header = ((Http2StreamSinkChannel) newFrame).generateSendFrameHeader();
if (header.getByteBuffer() == null) {
((Http2StreamSinkChannel) newFrame).clearHeader();
return false;
}
} catch (Exception e) {
UndertowLogger.REQUEST_LOGGER.debugf("Failed to generate header %s", newFrame);
}
}
pendingFrames.add(newFrame);
if (incrementIfAccepted) {
nextId += 2;
}
return true;
}
@Override
public void frameAdded(AbstractHttp2StreamSinkChannel addedFrame, List<AbstractHttp2StreamSinkChannel> pendingFrames, Deque<AbstractHttp2StreamSinkChannel> holdFrames) {
Iterator<AbstractHttp2StreamSinkChannel> it = holdFrames.iterator();
while (it.hasNext()) {
AbstractHttp2StreamSinkChannel pending = it.next();
boolean incrementNextId = false;
if ((pending.getChannel().isClient() && pending instanceof Http2HeadersStreamSinkChannel) ||
pending instanceof Http2PushPromiseStreamSinkChannel) {
if (pending instanceof Http2PushPromiseStreamSinkChannel) {
int streamId = ((Http2PushPromiseStreamSinkChannel) pending).getStreamId();
if (streamId > nextId) {
continue;
} else if (streamId == nextId) {
incrementNextId = true;
}
} else {
int streamId = ((Http2HeadersStreamSinkChannel) pending).getStreamId();
if (streamId > nextId) {
continue;
} else if (streamId == nextId) {
incrementNextId = true;
}
}
}
if (pending instanceof Http2StreamSinkChannel) {
SendFrameHeader header = ((Http2StreamSinkChannel) pending).generateSendFrameHeader();
if (header.getByteBuffer() != null) {
pendingFrames.add(pending);
it.remove();
it = holdFrames.iterator();
if (incrementNextId) {
nextId += 2;
}
} else {
((Http2StreamSinkChannel) pending).clearHeader();
}
}
}
}
}