package io.undertow.protocols.http2;
import java.io.IOException;
import java.nio.ByteBuffer;
import io.undertow.UndertowMessages;
public abstract class Http2PushBackParser {
private byte[] pushedBackData;
private boolean finished;
private int remainingData;
private final int frameLength;
int cnt;
public Http2PushBackParser(int frameLength) {
this.remainingData = frameLength;
this.frameLength = frameLength;
}
public void (ByteBuffer data, Http2FrameHeaderParser headerParser) throws IOException {
int used = 0;
ByteBuffer dataToParse = data;
int oldLimit = data.limit();
try {
if (pushedBackData != null) {
int toCopy = Math.min(remainingData - pushedBackData.length, data.remaining());
dataToParse = ByteBuffer.wrap(new byte[pushedBackData.length + toCopy]);
dataToParse.put(pushedBackData);
data.limit(data.position() + toCopy);
dataToParse.put(data);
dataToParse.flip();
}
if (dataToParse.remaining() > remainingData) {
dataToParse.limit(dataToParse.position() + remainingData);
}
int rem = dataToParse.remaining();
handleData(dataToParse, headerParser);
used = rem - dataToParse.remaining();
if(!isFinished() && remainingData > 0 && used == 0 && dataToParse.remaining() >= remainingData) {
if(cnt++ == 100) {
throw UndertowMessages.MESSAGES.parserDidNotMakeProgress();
}
}
} finally {
if (finished) {
data.limit(oldLimit);
return;
}
int leftOver = dataToParse.remaining();
if (leftOver > 0) {
pushedBackData = new byte[leftOver];
dataToParse.get(pushedBackData);
} else {
pushedBackData = null;
}
data.limit(oldLimit);
remainingData -= used;
if (remainingData == 0) {
finished = true;
}
}
}
protected abstract void handleData(ByteBuffer resource, Http2FrameHeaderParser headerParser) throws IOException;
public boolean isFinished() {
if(pushedBackData != null && remainingData == pushedBackData.length) {
return true;
}
return finished;
}
protected void finish() {
finished = true;
}
protected void moreData(int data) {
finished = false;
this.remainingData += data;
}
public int getFrameLength() {
return frameLength;
}
}