use of io.undertow.protocols.http2.Hpack.HeaderField in project undertow by undertow-io.
the class HpackDecoder method addEntryToHeaderTable.
private void addEntryToHeaderTable(HeaderField entry) {
if (entry.size > specifiedMemorySize) {
//it is to big to fit, so we just completely clear the table.
while (filledTableSlots > 0) {
headerTable[firstSlotPosition] = null;
firstSlotPosition++;
if (firstSlotPosition == headerTable.length) {
firstSlotPosition = 0;
}
filledTableSlots--;
}
currentMemorySize = 0;
return;
}
resizeIfRequired();
int newTableSlots = filledTableSlots + 1;
int tableLength = headerTable.length;
int index = (firstSlotPosition + filledTableSlots) % tableLength;
headerTable[index] = entry;
int newSize = currentMemorySize + entry.size;
while (newSize > specifiedMemorySize) {
int clearIndex = firstSlotPosition;
firstSlotPosition++;
if (firstSlotPosition == tableLength) {
firstSlotPosition = 0;
}
HeaderField oldData = headerTable[clearIndex];
headerTable[clearIndex] = null;
newSize -= oldData.size;
newTableSlots--;
}
this.filledTableSlots = newTableSlots;
currentMemorySize = newSize;
}
use of io.undertow.protocols.http2.Hpack.HeaderField in project undertow by undertow-io.
the class HpackDecoder method addStaticTableEntry.
private void addStaticTableEntry(int index) throws HpackException {
//adds an entry from the static table.
HeaderField entry = Hpack.STATIC_TABLE[index];
headerEmitter.emitHeader(entry.name, entry.value == null ? "" : entry.value, false);
}
use of io.undertow.protocols.http2.Hpack.HeaderField in project undertow by undertow-io.
the class HpackDecoder method decode.
/**
* Decodes the provided frame data. If this method leaves data in the buffer then
* this buffer should be compacted so this data is preserved, unless there is no
* more data in which case this should be considered a protocol error.
*
* @param buffer The buffer
*/
public void decode(ByteBuffer buffer, boolean moreData) throws HpackException {
while (buffer.hasRemaining()) {
int originalPos = buffer.position();
byte b = buffer.get();
if ((b & 0b10000000) != 0) {
first = false;
//if the first bit is set it is an indexed header field
//unget the byte
buffer.position(buffer.position() - 1);
//prefix is 7
int index = Hpack.decodeInteger(buffer, 7);
if (index == -1) {
if (!moreData) {
throw UndertowMessages.MESSAGES.hpackFailed();
}
buffer.position(originalPos);
return;
} else if (index == 0) {
throw UndertowMessages.MESSAGES.zeroNotValidHeaderTableIndex();
}
handleIndex(index);
} else if ((b & 0b01000000) != 0) {
first = false;
//Literal Header Field with Incremental Indexing
HttpString headerName = readHeaderName(buffer, 6);
if (headerName == null) {
if (!moreData) {
throw UndertowMessages.MESSAGES.hpackFailed();
}
buffer.position(originalPos);
return;
}
String headerValue = readHpackString(buffer);
if (headerValue == null) {
if (!moreData) {
throw UndertowMessages.MESSAGES.hpackFailed();
}
buffer.position(originalPos);
return;
}
headerEmitter.emitHeader(headerName, headerValue, false);
addEntryToHeaderTable(new HeaderField(headerName, headerValue));
} else if ((b & 0b11110000) == 0) {
first = false;
//Literal Header Field without Indexing
HttpString headerName = readHeaderName(buffer, 4);
if (headerName == null) {
if (!moreData) {
throw UndertowMessages.MESSAGES.hpackFailed();
}
buffer.position(originalPos);
return;
}
String headerValue = readHpackString(buffer);
if (headerValue == null) {
if (!moreData) {
throw UndertowMessages.MESSAGES.hpackFailed();
}
buffer.position(originalPos);
return;
}
headerEmitter.emitHeader(headerName, headerValue, false);
} else if ((b & 0b11110000) == 0b00010000) {
first = false;
//Literal Header Field never indexed
HttpString headerName = readHeaderName(buffer, 4);
if (headerName == null) {
buffer.position(originalPos);
return;
}
String headerValue = readHpackString(buffer);
if (headerValue == null) {
if (!moreData) {
throw UndertowMessages.MESSAGES.hpackFailed();
}
buffer.position(originalPos);
return;
}
headerEmitter.emitHeader(headerName, headerValue, true);
} else if ((b & 0b11100000) == 0b00100000) {
if (!first) {
throw new HpackException();
}
//context update max table size change
if (!handleMaxMemorySizeChange(buffer, originalPos)) {
return;
}
} else {
throw UndertowMessages.MESSAGES.invalidHpackEncoding(b);
}
}
if (!moreData) {
first = true;
}
}
use of io.undertow.protocols.http2.Hpack.HeaderField in project undertow by undertow-io.
the class HpackDecoder method handleIndexedHeaderName.
private HttpString handleIndexedHeaderName(int index) throws HpackException {
if (index <= Hpack.STATIC_TABLE_LENGTH) {
return Hpack.STATIC_TABLE[index].name;
} else {
if (index >= Hpack.STATIC_TABLE_LENGTH + filledTableSlots) {
throw new HpackException();
}
int adjustedIndex = getRealIndex(index - Hpack.STATIC_TABLE_LENGTH);
HeaderField res = headerTable[adjustedIndex];
if (res == null) {
throw new HpackException();
}
return res.name;
}
}
use of io.undertow.protocols.http2.Hpack.HeaderField in project undertow by undertow-io.
the class HpackDecoder method handleMaxMemorySizeChange.
private boolean handleMaxMemorySizeChange(ByteBuffer buffer, int originalPos) throws HpackException {
//unget the byte
buffer.position(buffer.position() - 1);
int size = Hpack.decodeInteger(buffer, 5);
if (size == -1) {
buffer.position(originalPos);
return false;
}
if (size > maxAllowedMemorySize) {
throw new HpackException(Http2Channel.ERROR_PROTOCOL_ERROR);
}
specifiedMemorySize = size;
if (currentMemorySize > specifiedMemorySize) {
int newTableSlots = filledTableSlots;
int tableLength = headerTable.length;
int newSize = currentMemorySize;
while (newSize > specifiedMemorySize) {
int clearIndex = firstSlotPosition;
firstSlotPosition++;
if (firstSlotPosition == tableLength) {
firstSlotPosition = 0;
}
HeaderField oldData = headerTable[clearIndex];
headerTable[clearIndex] = null;
newSize -= oldData.size;
newTableSlots--;
}
this.filledTableSlots = newTableSlots;
currentMemorySize = newSize;
}
return true;
}
Aggregations