/** *EncoderforHPACKframes.
*/ class HpackEncoder {
privatestaticfinal Log log = LogFactory.getLog(HpackEncoder.class); privatestaticfinal StringManager sm = StringManager.getManager(HpackEncoder.class);
privatestaticfinal HpackHeaderFunction DEFAULT_HEADER_FUNCTION = new HpackHeaderFunction() {
@Override publicboolean shouldUseIndexing(String headerName, String value) { // content length and date change all the time // no need to index them, or they will churn the table switch (headerName) { case"content-length": case"date": returnfalse; default: returntrue;
}
}
@Override publicboolean shouldUseHuffman(String header, String value) { return value.length() > 5; // TODO: figure out a good value for this
}
@Override publicboolean shouldUseHuffman(String header) { return header.length() > 5; // TODO: figure out a good value for this
}
privateint newMaxHeaderSize = -1; // if the max header size has been changed privateint minNewMaxHeaderSize = -1; // records the smallest value of newMaxHeaderSize, as per section 4.1
privatefinal Deque<TableEntry> evictionQueue = new ArrayDeque<>(); privatefinal Map<String,List<TableEntry>> dynamicTable = new HashMap<>(); // TODO: use a custom data structure to // reduce allocations
static {
Map<String,TableEntry[]> map = new HashMap<>(); for (int i = 1; i < Hpack.STATIC_TABLE.length; ++i) {
Hpack.HeaderField m = Hpack.STATIC_TABLE[i];
TableEntry[] existing = map.get(m.name); if (existing == null) {
map.put(m.name, new TableEntry[] { new TableEntry(m.name, m.value, i) });
} else {
TableEntry[] newEntry = new TableEntry[existing.length + 1];
System.arraycopy(existing, 0, newEntry, 0, existing.length);
newEntry[existing.length] = new TableEntry(m.name, m.value, i);
map.put(m.name, newEntry);
}
}
ENCODING_STATIC_TABLE = Collections.unmodifiableMap(map);
}
privatevoid writeHuffmanEncodableName(ByteBuffer target, String headerName) { if (hpackHeaderFunction.shouldUseHuffman(headerName)) { if (HPackHuffman.encode(target, headerName, true)) { return;
}
}
target.put((byte) 0); // to use encodeInteger we need to place the first byte in the buffer.
Hpack.encodeInteger(target, headerName.length(), 7); for (int j = 0; j < headerName.length(); ++j) {
target.put((byte) Hpack.toLower(headerName.charAt(j)));
}
privatevoid writeValueString(ByteBuffer target, String val) {
target.put((byte) 0); // to use encodeInteger we need to place the first byte in the buffer.
Hpack.encodeInteger(target, val.length(), 7); for (int j = 0; j < val.length(); ++j) {
target.put((byte) val.charAt(j));
}
}
privatevoid addToDynamicTable(String headerName, String val) { int pos = entryPositionCounter++;
DynamicTableEntry d = new DynamicTableEntry(headerName, val, -pos);
dynamicTable.computeIfAbsent(headerName, k -> new ArrayList<>(1)).add(d);
evictionQueue.add(d);
currentTableSize += d.getSize();
runEvictionIfRequired(); if (entryPositionCounter == Integer.MAX_VALUE) { // prevent rollover
preventPositionRollover();
}
}
privatevoid preventPositionRollover() { // if the position counter is about to roll over we iterate all the table entries // and set their position to their actual position for (List<TableEntry> tableEntries : dynamicTable.values()) { for (TableEntry t : tableEntries) {
t.position = t.getPosition();
}
}
entryPositionCounter = 0;
}
privatevoid runEvictionIfRequired() {
while (currentTableSize > maxTableSize) {
TableEntry next = evictionQueue.poll(); if (next == null) { return;
}
currentTableSize -= next.size;
List<TableEntry> list = dynamicTable.get(next.name);
list.remove(next); if (list.isEmpty()) {
dynamicTable.remove(next.name);
}
}
}
private TableEntry findInTable(String headerName, String value) {
TableEntry[] staticTable = ENCODING_STATIC_TABLE.get(headerName); if (staticTable != null) { for (TableEntry st : staticTable) { if (st.value != null && st.value.equals(value)) { // todo: some form of lookup? return st;
}
}
}
List<TableEntry> dynamic = dynamicTable.get(headerName); if (dynamic != null) { for (TableEntry st : dynamic) { if (st.value.equals(value)) { // todo: some form of lookup? return st;
}
}
} if (staticTable != null) { return staticTable[0];
} returnnull;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.11Bemerkung:
(vorverarbeitet am 2026-10-04)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.