Refactor QPACK to use an internal package for non API classes.
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
f9606770b3
commit
ea70f599bb
|
@ -17,9 +17,6 @@ import org.eclipse.jetty.http3.qpack.QpackFieldPreEncoder;
|
|||
module org.eclipse.jetty.http3.qpack
|
||||
{
|
||||
exports org.eclipse.jetty.http3.qpack;
|
||||
exports org.eclipse.jetty.http3.qpack.table;
|
||||
exports org.eclipse.jetty.http3.qpack.generator;
|
||||
exports org.eclipse.jetty.http3.qpack.parser;
|
||||
|
||||
requires transitive org.eclipse.jetty.http;
|
||||
requires org.slf4j;
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
||||
public class HuffmanDecoder
|
||||
{
|
||||
static final char EOS = Huffman.EOS;
|
||||
static final char[] tree = Huffman.tree;
|
||||
static final char[] rowsym = Huffman.rowsym;
|
||||
static final byte[] rowbits = Huffman.rowbits;
|
||||
|
||||
private final Utf8StringBuilder utf8 = new Utf8StringBuilder();
|
||||
private int count = 0;
|
||||
private int node = 0;
|
||||
private int current = 0;
|
||||
private int bits = 0;
|
||||
|
||||
public String decode(ByteBuffer buffer, int length) throws QpackException.CompressionException
|
||||
{
|
||||
for (; count < length; count++)
|
||||
{
|
||||
if (!buffer.hasRemaining())
|
||||
return null;
|
||||
|
||||
int b = buffer.get() & 0xFF;
|
||||
current = (current << 8) | b;
|
||||
bits += 8;
|
||||
while (bits >= 8)
|
||||
{
|
||||
int c = (current >>> (bits - 8)) & 0xFF;
|
||||
node = tree[node * 256 + c];
|
||||
if (rowbits[node] != 0)
|
||||
{
|
||||
if (rowsym[node] == EOS)
|
||||
{
|
||||
reset();
|
||||
throw new QpackException.CompressionException("EOS in content");
|
||||
}
|
||||
|
||||
// terminal node
|
||||
utf8.append((byte)(0xFF & rowsym[node]));
|
||||
bits -= rowbits[node];
|
||||
node = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-terminal node
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (bits > 0)
|
||||
{
|
||||
int c = (current << (8 - bits)) & 0xFF;
|
||||
int lastNode = node;
|
||||
node = tree[node * 256 + c];
|
||||
|
||||
if (rowbits[node] == 0 || rowbits[node] > bits)
|
||||
{
|
||||
int requiredPadding = 0;
|
||||
for (int i = 0; i < bits; i++)
|
||||
{
|
||||
requiredPadding = (requiredPadding << 1) | 1;
|
||||
}
|
||||
|
||||
if ((c >> (8 - bits)) != requiredPadding)
|
||||
throw new QpackException.CompressionException("Incorrect padding");
|
||||
|
||||
node = lastNode;
|
||||
break;
|
||||
}
|
||||
|
||||
utf8.append((byte)(0xFF & rowsym[node]));
|
||||
bits -= rowbits[node];
|
||||
node = 0;
|
||||
}
|
||||
|
||||
if (node != 0)
|
||||
throw new QpackException.CompressionException("Bad termination");
|
||||
|
||||
return utf8.toString();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
utf8.reset();
|
||||
count = 0;
|
||||
current = 0;
|
||||
node = 0;
|
||||
bits = 0;
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
|
|
@ -21,15 +21,15 @@ import java.util.List;
|
|||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http3.qpack.generator.InsertCountIncrementInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.SectionAcknowledgmentInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.parser.DecoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.parser.EncodedFieldSection;
|
||||
import org.eclipse.jetty.http3.qpack.parser.NBitIntegerParser;
|
||||
import org.eclipse.jetty.http3.qpack.table.DynamicTable;
|
||||
import org.eclipse.jetty.http3.qpack.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.table.StaticTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.QpackContext;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.InsertCountIncrementInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.SectionAcknowledgmentInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.parser.DecoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.parser.EncodedFieldSection;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.DynamicTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.StaticTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -46,7 +46,6 @@ public class QpackDecoder implements Dumpable
|
|||
|
||||
private final Handler _handler;
|
||||
private final QpackContext _context;
|
||||
private final MetaDataBuilder _builder;
|
||||
private final DecoderInstructionParser _parser;
|
||||
|
||||
private final List<EncodedFieldSection> _encodedFieldSections = new ArrayList<>();
|
||||
|
@ -58,12 +57,11 @@ public class QpackDecoder implements Dumpable
|
|||
public QpackDecoder(Handler handler, int maxHeaderSize)
|
||||
{
|
||||
_context = new QpackContext();
|
||||
_builder = new MetaDataBuilder(maxHeaderSize);
|
||||
_handler = handler;
|
||||
_parser = new DecoderInstructionParser(new DecoderAdapter());
|
||||
}
|
||||
|
||||
public QpackContext getQpackContext()
|
||||
QpackContext getQpackContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
@ -83,8 +81,8 @@ public class QpackDecoder implements Dumpable
|
|||
LOG.debug(String.format("CtxTbl[%x] decoding %d octets", _context.hashCode(), buffer.remaining()));
|
||||
|
||||
// If the buffer is big, don't even think about decoding it
|
||||
if (buffer.remaining() > _builder.getMaxSize())
|
||||
throw new QpackException.SessionException("431 Request Header Fields too large");
|
||||
// if (buffer.remaining() > _builder.getMaxSize())
|
||||
//throw new QpackException.SessionException("431 Request Header Fields too large");
|
||||
|
||||
_integerDecoder.setPrefix(8);
|
||||
int encodedInsertCount = _integerDecoder.decode(buffer);
|
||||
|
@ -235,6 +233,9 @@ public class QpackDecoder implements Dumpable
|
|||
return String.format("QpackDecoder@%x{%s}", hashCode(), _context);
|
||||
}
|
||||
|
||||
/**
|
||||
* This delivers notifications from the DecoderInstruction parser directly into the Decoder.
|
||||
*/
|
||||
class DecoderAdapter implements DecoderInstructionParser.Handler
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -28,14 +28,17 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http3.qpack.generator.DuplicateInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.IndexedNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.LiteralNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.SetCapacityInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.parser.EncoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.table.DynamicTable;
|
||||
import org.eclipse.jetty.http3.qpack.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.EncodableEntry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.QpackContext;
|
||||
import org.eclipse.jetty.http3.qpack.internal.StreamInfo;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.DuplicateInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.IndexedNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.LiteralNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.SetCapacityInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.parser.EncoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.DynamicTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.NullByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
@ -126,7 +129,7 @@ public class QpackEncoder implements Dumpable
|
|||
_parser = new EncoderInstructionParser(new EncoderAdapter());
|
||||
}
|
||||
|
||||
public QpackContext getQpackContext()
|
||||
QpackContext getQpackContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
@ -302,8 +305,8 @@ public class QpackEncoder implements Dumpable
|
|||
|
||||
// Calculate the size required. TODO: it may be more efficient to just use a buffer of MAX_HEADER_SIZE?
|
||||
int spaceRequired = 0;
|
||||
spaceRequired += 1 + NBitInteger.octectsNeeded(8, encodedInsertCount);
|
||||
spaceRequired += 1 + NBitInteger.octectsNeeded(7, deltaBase);
|
||||
spaceRequired += 1 + NBitIntegerEncoder.octectsNeeded(8, encodedInsertCount);
|
||||
spaceRequired += 1 + NBitIntegerEncoder.octectsNeeded(7, deltaBase);
|
||||
for (EncodableEntry encodableEntry : encodableEntries)
|
||||
{
|
||||
spaceRequired += encodableEntry.getRequiredSize(base);
|
||||
|
@ -313,9 +316,9 @@ public class QpackEncoder implements Dumpable
|
|||
int pos = BufferUtil.flipToFill(buffer);
|
||||
|
||||
// Encode the Field Section Prefix into the ByteBuffer.
|
||||
NBitInteger.encode(buffer, 8, encodedInsertCount);
|
||||
NBitIntegerEncoder.encode(buffer, 8, encodedInsertCount);
|
||||
buffer.put(signBit ? (byte)0x80 : (byte)0x00);
|
||||
NBitInteger.encode(buffer, 7, deltaBase);
|
||||
NBitIntegerEncoder.encode(buffer, 7, deltaBase);
|
||||
|
||||
// Encode the field lines into the ByteBuffer.
|
||||
for (EncodableEntry entry : encodableEntries)
|
||||
|
|
|
@ -19,8 +19,10 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpFieldPreEncoder;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http3.qpack.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.table.StaticTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.EncodableEntry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.QpackContext;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.StaticTable;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
public class QpackFieldPreEncoder implements HttpFieldPreEncoder
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
|
@ -19,35 +19,37 @@ import java.util.Objects;
|
|||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http3.qpack.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.HuffmanEncoder;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
|
||||
abstract class EncodableEntry
|
||||
public abstract class EncodableEntry
|
||||
{
|
||||
static EncodableEntry getReferencedEntry(Entry entry)
|
||||
public static EncodableEntry getReferencedEntry(Entry entry)
|
||||
{
|
||||
return new ReferencedEntry(entry);
|
||||
}
|
||||
|
||||
static EncodableEntry getNameReferencedEntry(Entry nameEntry, HttpField field, boolean huffman)
|
||||
public static EncodableEntry getNameReferencedEntry(Entry nameEntry, HttpField field, boolean huffman)
|
||||
{
|
||||
return new ReferencedNameEntry(nameEntry, field, huffman);
|
||||
}
|
||||
|
||||
static EncodableEntry getLiteralEntry(HttpField field, boolean huffman)
|
||||
public static EncodableEntry getLiteralEntry(HttpField field, boolean huffman)
|
||||
{
|
||||
return new LiteralEntry(field, huffman);
|
||||
}
|
||||
|
||||
static EncodableEntry getPreEncodedEntry(PreEncodedHttpField httpField)
|
||||
public static EncodableEntry getPreEncodedEntry(PreEncodedHttpField httpField)
|
||||
{
|
||||
return new PreEncodedEntry(httpField);
|
||||
}
|
||||
|
||||
abstract void encode(ByteBuffer buffer, int base);
|
||||
public abstract void encode(ByteBuffer buffer, int base);
|
||||
|
||||
abstract int getRequiredSize(int base);
|
||||
public abstract int getRequiredSize(int base);
|
||||
|
||||
abstract int getRequiredInsertCount();
|
||||
public abstract int getRequiredInsertCount();
|
||||
|
||||
private static class ReferencedEntry extends EncodableEntry
|
||||
{
|
||||
|
@ -67,21 +69,21 @@ abstract class EncodableEntry
|
|||
// Indexed Field Line with Static Reference.
|
||||
buffer.put((byte)(0x80 | 0x40));
|
||||
int relativeIndex = _entry.getIndex();
|
||||
NBitInteger.encode(buffer, 6, relativeIndex);
|
||||
NBitIntegerEncoder.encode(buffer, 6, relativeIndex);
|
||||
}
|
||||
else if (_entry.getIndex() < base)
|
||||
{
|
||||
// Indexed Field Line with Dynamic Reference.
|
||||
buffer.put((byte)0x80);
|
||||
int relativeIndex = base - (_entry.getIndex() + 1);
|
||||
NBitInteger.encode(buffer, 6, relativeIndex);
|
||||
NBitIntegerEncoder.encode(buffer, 6, relativeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indexed Field Line with Post-Base Index.
|
||||
buffer.put((byte)0x10);
|
||||
int relativeIndex = _entry.getIndex() - base;
|
||||
NBitInteger.encode(buffer, 4, relativeIndex);
|
||||
NBitIntegerEncoder.encode(buffer, 4, relativeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,19 +95,19 @@ abstract class EncodableEntry
|
|||
{
|
||||
// Indexed Field Line with Static Reference.
|
||||
int relativeIndex = _entry.getIndex();
|
||||
return 1 + NBitInteger.octectsNeeded(6, relativeIndex);
|
||||
return 1 + NBitIntegerEncoder.octectsNeeded(6, relativeIndex);
|
||||
}
|
||||
else if (_entry.getIndex() < base)
|
||||
{
|
||||
// Indexed Field Line with Dynamic Reference.
|
||||
int relativeIndex = base - (_entry.getIndex() + 1);
|
||||
return 1 + NBitInteger.octectsNeeded(6, relativeIndex);
|
||||
return 1 + NBitIntegerEncoder.octectsNeeded(6, relativeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indexed Field Line with Post-Base Index.
|
||||
int relativeIndex = _entry.getIndex() - base;
|
||||
return 1 + NBitInteger.octectsNeeded(4, relativeIndex);
|
||||
return 1 + NBitIntegerEncoder.octectsNeeded(4, relativeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,21 +145,21 @@ abstract class EncodableEntry
|
|||
// Literal Field Line with Static Name Reference.
|
||||
buffer.put((byte)(0x40 | allowIntermediary | 0x10));
|
||||
int relativeIndex = _nameEntry.getIndex();
|
||||
NBitInteger.encode(buffer, 4, relativeIndex);
|
||||
NBitIntegerEncoder.encode(buffer, 4, relativeIndex);
|
||||
}
|
||||
else if (_nameEntry.getIndex() < base)
|
||||
{
|
||||
// Literal Field Line with Dynamic Name Reference.
|
||||
buffer.put((byte)(0x40 | allowIntermediary));
|
||||
int relativeIndex = base - (_nameEntry.getIndex() + 1);
|
||||
NBitInteger.encode(buffer, 4, relativeIndex);
|
||||
NBitIntegerEncoder.encode(buffer, 4, relativeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Literal Field Line with Post-Base Name Reference.
|
||||
buffer.put(allowIntermediary);
|
||||
int relativeIndex = _nameEntry.getIndex() - base;
|
||||
NBitInteger.encode(buffer, 3, relativeIndex);
|
||||
NBitIntegerEncoder.encode(buffer, 3, relativeIndex);
|
||||
}
|
||||
|
||||
// Encode the value.
|
||||
|
@ -165,13 +167,13 @@ abstract class EncodableEntry
|
|||
if (_huffman)
|
||||
{
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(value));
|
||||
Huffman.encode(buffer, value);
|
||||
NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(value));
|
||||
HuffmanEncoder.encode(buffer, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.put((byte)0x00);
|
||||
NBitInteger.encode(buffer, 7, value.length());
|
||||
NBitIntegerEncoder.encode(buffer, 7, value.length());
|
||||
buffer.put(value.getBytes());
|
||||
}
|
||||
}
|
||||
|
@ -181,8 +183,8 @@ abstract class EncodableEntry
|
|||
{
|
||||
String value = getValue();
|
||||
int relativeIndex = _nameEntry.getIndex() - base;
|
||||
int valueLength = _huffman ? Huffman.octetsNeeded(value) : value.length();
|
||||
return 1 + NBitInteger.octectsNeeded(4, relativeIndex) + 1 + NBitInteger.octectsNeeded(7, valueLength) + valueLength;
|
||||
int valueLength = _huffman ? HuffmanEncoder.octetsNeeded(value) : value.length();
|
||||
return 1 + NBitIntegerEncoder.octectsNeeded(4, relativeIndex) + 1 + NBitIntegerEncoder.octectsNeeded(7, valueLength) + valueLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -220,20 +222,20 @@ abstract class EncodableEntry
|
|||
if (_huffman)
|
||||
{
|
||||
buffer.put((byte)(0x28 | allowIntermediary));
|
||||
NBitInteger.encode(buffer, 3, Huffman.octetsNeeded(name));
|
||||
Huffman.encode(buffer, name);
|
||||
NBitIntegerEncoder.encode(buffer, 3, HuffmanEncoder.octetsNeeded(name));
|
||||
HuffmanEncoder.encode(buffer, name);
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(value));
|
||||
Huffman.encode(buffer, value);
|
||||
NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(value));
|
||||
HuffmanEncoder.encode(buffer, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: What charset should we be using? (this applies to the instruction generators as well).
|
||||
buffer.put((byte)(0x20 | allowIntermediary));
|
||||
NBitInteger.encode(buffer, 3, name.length());
|
||||
NBitIntegerEncoder.encode(buffer, 3, name.length());
|
||||
buffer.put(name.getBytes());
|
||||
buffer.put((byte)0x00);
|
||||
NBitInteger.encode(buffer, 7, value.length());
|
||||
NBitIntegerEncoder.encode(buffer, 7, value.length());
|
||||
buffer.put(value.getBytes());
|
||||
}
|
||||
}
|
||||
|
@ -243,9 +245,9 @@ abstract class EncodableEntry
|
|||
{
|
||||
String name = getName();
|
||||
String value = getValue();
|
||||
int nameLength = _huffman ? Huffman.octetsNeeded(name) : name.length();
|
||||
int valueLength = _huffman ? Huffman.octetsNeeded(value) : value.length();
|
||||
return 2 + NBitInteger.octectsNeeded(3, nameLength) + nameLength + NBitInteger.octectsNeeded(7, valueLength) + valueLength;
|
||||
int nameLength = _huffman ? HuffmanEncoder.octetsNeeded(name) : name.length();
|
||||
int valueLength = _huffman ? HuffmanEncoder.octetsNeeded(value) : value.length();
|
||||
return 2 + NBitIntegerEncoder.octectsNeeded(3, nameLength) + nameLength + NBitIntegerEncoder.octectsNeeded(7, valueLength) + valueLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -267,6 +269,7 @@ abstract class EncodableEntry
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: pass in the HTTP version to avoid hard coding HTTP3?
|
||||
private static class PreEncodedEntry extends EncodableEntry
|
||||
{
|
||||
private final PreEncodedHttpField _httpField;
|
|
@ -11,12 +11,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http3.qpack.table.DynamicTable;
|
||||
import org.eclipse.jetty.http3.qpack.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.table.StaticTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.DynamicTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.StaticTable;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
@ -19,9 +19,9 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.table.Entry;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
||||
|
||||
class StreamInfo implements Iterable<StreamInfo.SectionInfo>
|
||||
public class StreamInfo implements Iterable<StreamInfo.SectionInfo>
|
||||
{
|
||||
private final int _streamId;
|
||||
private final Queue<SectionInfo> _sectionInfos = new LinkedList<>();
|
|
@ -11,11 +11,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack.internal.instruction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
import org.eclipse.jetty.http3.qpack.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
|
@ -36,10 +37,10 @@ public class DuplicateInstruction implements Instruction
|
|||
@Override
|
||||
public void encode(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int size = NBitInteger.octectsNeeded(5, _index) + 1;
|
||||
int size = NBitIntegerEncoder.octectsNeeded(5, _index) + 1;
|
||||
ByteBuffer buffer = lease.acquire(size, false);
|
||||
buffer.put((byte)0x00);
|
||||
NBitInteger.encode(buffer, 5, _index);
|
||||
NBitIntegerEncoder.encode(buffer, 5, _index);
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
lease.append(buffer, true);
|
||||
}
|
|
@ -11,12 +11,13 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack.internal.instruction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.Huffman;
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
import org.eclipse.jetty.http3.qpack.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.HuffmanEncoder;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
|
@ -53,24 +54,24 @@ public class IndexedNameEntryInstruction implements Instruction
|
|||
@Override
|
||||
public void encode(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int size = NBitInteger.octectsNeeded(6, _index) + (_huffman ? Huffman.octetsNeeded(_value) : _value.length()) + 2;
|
||||
int size = NBitIntegerEncoder.octectsNeeded(6, _index) + (_huffman ? HuffmanEncoder.octetsNeeded(_value) : _value.length()) + 2;
|
||||
ByteBuffer buffer = lease.acquire(size, false);
|
||||
|
||||
// First bit indicates the instruction, second bit is whether it is a dynamic table reference or not.
|
||||
buffer.put((byte)(0x80 | (_dynamic ? 0x00 : 0x40)));
|
||||
NBitInteger.encode(buffer, 6, _index);
|
||||
NBitIntegerEncoder.encode(buffer, 6, _index);
|
||||
|
||||
// We will not huffman encode the string.
|
||||
if (_huffman)
|
||||
{
|
||||
buffer.put((byte)(0x80));
|
||||
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(_value));
|
||||
Huffman.encode(buffer, _value);
|
||||
NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(_value));
|
||||
HuffmanEncoder.encode(buffer, _value);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.put((byte)(0x00));
|
||||
NBitInteger.encode(buffer, 7, _value.length());
|
||||
NBitIntegerEncoder.encode(buffer, 7, _value.length());
|
||||
buffer.put(_value.getBytes());
|
||||
}
|
||||
|
|
@ -11,11 +11,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack.internal.instruction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
import org.eclipse.jetty.http3.qpack.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
|
@ -31,10 +32,10 @@ public class InsertCountIncrementInstruction implements Instruction
|
|||
@Override
|
||||
public void encode(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int size = NBitInteger.octectsNeeded(6, _increment) + 1;
|
||||
int size = NBitIntegerEncoder.octectsNeeded(6, _increment) + 1;
|
||||
ByteBuffer buffer = lease.acquire(size, false);
|
||||
buffer.put((byte)0x00);
|
||||
NBitInteger.encode(buffer, 6, _increment);
|
||||
NBitIntegerEncoder.encode(buffer, 6, _increment);
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
lease.append(buffer, true);
|
||||
}
|
|
@ -11,12 +11,13 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack.internal.instruction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.Huffman;
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
import org.eclipse.jetty.http3.qpack.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.HuffmanEncoder;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
|
@ -48,33 +49,33 @@ public class LiteralNameEntryInstruction implements Instruction
|
|||
@Override
|
||||
public void encode(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int size = (_huffmanName ? Huffman.octetsNeeded(_name) : _name.length()) +
|
||||
(_huffmanValue ? Huffman.octetsNeeded(_value) : _value.length()) + 2;
|
||||
int size = (_huffmanName ? HuffmanEncoder.octetsNeeded(_name) : _name.length()) +
|
||||
(_huffmanValue ? HuffmanEncoder.octetsNeeded(_value) : _value.length()) + 2;
|
||||
ByteBuffer buffer = lease.acquire(size, false);
|
||||
|
||||
if (_huffmanName)
|
||||
{
|
||||
buffer.put((byte)(0x40 | 0x20));
|
||||
NBitInteger.encode(buffer, 5, Huffman.octetsNeeded(_name));
|
||||
Huffman.encode(buffer, _name);
|
||||
NBitIntegerEncoder.encode(buffer, 5, HuffmanEncoder.octetsNeeded(_name));
|
||||
HuffmanEncoder.encode(buffer, _name);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.put((byte)(0x40));
|
||||
NBitInteger.encode(buffer, 5, _name.length());
|
||||
NBitIntegerEncoder.encode(buffer, 5, _name.length());
|
||||
buffer.put(_name.getBytes());
|
||||
}
|
||||
|
||||
if (_huffmanValue)
|
||||
{
|
||||
buffer.put((byte)(0x80));
|
||||
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(_value));
|
||||
Huffman.encode(buffer, _value);
|
||||
NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(_value));
|
||||
HuffmanEncoder.encode(buffer, _value);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.put((byte)(0x00));
|
||||
NBitInteger.encode(buffer, 5, _value.length());
|
||||
NBitIntegerEncoder.encode(buffer, 5, _value.length());
|
||||
buffer.put(_value.getBytes());
|
||||
}
|
||||
|
|
@ -11,11 +11,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack.internal.instruction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
import org.eclipse.jetty.http3.qpack.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
|
@ -31,10 +32,10 @@ public class SectionAcknowledgmentInstruction implements Instruction
|
|||
@Override
|
||||
public void encode(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int size = NBitInteger.octectsNeeded(7, _streamId) + 1;
|
||||
int size = NBitIntegerEncoder.octectsNeeded(7, _streamId) + 1;
|
||||
ByteBuffer buffer = lease.acquire(size, false);
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer, 7, _streamId);
|
||||
NBitIntegerEncoder.encode(buffer, 7, _streamId);
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
lease.append(buffer, true);
|
||||
}
|
|
@ -11,11 +11,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack.internal.instruction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
import org.eclipse.jetty.http3.qpack.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
|
@ -36,10 +37,10 @@ public class SetCapacityInstruction implements Instruction
|
|||
@Override
|
||||
public void encode(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int size = NBitInteger.octectsNeeded(5, _capacity) + 1;
|
||||
int size = NBitIntegerEncoder.octectsNeeded(5, _capacity) + 1;
|
||||
ByteBuffer buffer = lease.acquire(size, false);
|
||||
buffer.put((byte)0x20);
|
||||
NBitInteger.encode(buffer, 5, _capacity);
|
||||
NBitIntegerEncoder.encode(buffer, 5, _capacity);
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
lease.append(buffer, true);
|
||||
}
|
|
@ -11,11 +11,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.generator;
|
||||
package org.eclipse.jetty.http3.qpack.internal.instruction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
import org.eclipse.jetty.http3.qpack.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
||||
|
@ -31,10 +32,10 @@ public class StreamCancellationInstruction implements Instruction
|
|||
@Override
|
||||
public void encode(ByteBufferPool.Lease lease)
|
||||
{
|
||||
int size = NBitInteger.octectsNeeded(6, _streamId) + 1;
|
||||
int size = NBitIntegerEncoder.octectsNeeded(6, _streamId) + 1;
|
||||
ByteBuffer buffer = lease.acquire(size, false);
|
||||
buffer.put((byte)0x40);
|
||||
NBitInteger.encode(buffer, 6, _streamId);
|
||||
NBitIntegerEncoder.encode(buffer, 6, _streamId);
|
||||
BufferUtil.flipToFlush(buffer, 0);
|
||||
lease.append(buffer, true);
|
||||
}
|
|
@ -11,11 +11,13 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.parser;
|
||||
package org.eclipse.jetty.http3.qpack.internal.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitStringParser;
|
||||
|
||||
/**
|
||||
* Parses a stream of unframed instructions for the Decoder. These instructions are sent from the remote Encoder.
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.parser;
|
||||
package org.eclipse.jetty.http3.qpack.internal.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
|
@ -19,8 +19,10 @@ import java.util.List;
|
|||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http3.qpack.QpackContext;
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.http3.qpack.internal.QpackContext;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitStringParser;
|
||||
|
||||
public class EncodedFieldSection
|
||||
{
|
|
@ -11,11 +11,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.parser;
|
||||
package org.eclipse.jetty.http3.qpack.internal.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
|
||||
/**
|
||||
* Parses a stream of unframed instructions for the Encoder. These instructions are sent from the remote Decoder.
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.table;
|
||||
package org.eclipse.jetty.http3.qpack.internal.table;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
|
@ -11,11 +11,14 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.table;
|
||||
package org.eclipse.jetty.http3.qpack.internal.table;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.HuffmanEncoder;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
public class Entry
|
||||
|
@ -88,7 +91,7 @@ public class Entry
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x{index=%d, refs=%d, field=\"%s\"}", getClass().getSimpleName(), hashCode(),
|
||||
return String.format("%s@%x{index=%d, refs=%d, field=\"%s\"}", getClass().getSimpleName(), hashCode(),
|
||||
_absoluteIndex, _referenceCount.get(), _field);
|
||||
}
|
||||
|
||||
|
@ -101,4 +104,53 @@ public class Entry
|
|||
{
|
||||
return 32 + StringUtil.getLength(field.getName()) + StringUtil.getLength(field.getValue());
|
||||
}
|
||||
|
||||
public static class StaticEntry extends Entry
|
||||
{
|
||||
private final byte[] _huffmanValue;
|
||||
private final byte _encodedField;
|
||||
|
||||
StaticEntry(int index, HttpField field)
|
||||
{
|
||||
super(index, field);
|
||||
String value = field.getValue();
|
||||
if (value != null && value.length() > 0)
|
||||
{
|
||||
int huffmanLen = HuffmanEncoder.octetsNeeded(value);
|
||||
if (huffmanLen < 0)
|
||||
throw new IllegalStateException("bad value");
|
||||
int lenLen = NBitIntegerEncoder.octectsNeeded(7, huffmanLen);
|
||||
_huffmanValue = new byte[1 + lenLen + huffmanLen];
|
||||
ByteBuffer buffer = ByteBuffer.wrap(_huffmanValue);
|
||||
|
||||
// Indicate Huffman
|
||||
buffer.put((byte)0x80);
|
||||
// Add huffman length
|
||||
NBitIntegerEncoder.encode(buffer, 7, huffmanLen);
|
||||
// Encode value
|
||||
HuffmanEncoder.encode(buffer, value);
|
||||
}
|
||||
else
|
||||
_huffmanValue = null;
|
||||
|
||||
_encodedField = (byte)(0x80 | index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getStaticHuffmanValue()
|
||||
{
|
||||
return _huffmanValue;
|
||||
}
|
||||
|
||||
public byte getEncodedField()
|
||||
{
|
||||
return _encodedField;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.table;
|
||||
package org.eclipse.jetty.http3.qpack.internal.table;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
@ -24,7 +24,7 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http3.qpack.StaticTableHttpField;
|
||||
import org.eclipse.jetty.http3.qpack.internal.unused.StaticTableHttpField;
|
||||
import org.eclipse.jetty.util.Index;
|
||||
|
||||
public class StaticTable implements Iterable<Entry>
|
||||
|
@ -135,17 +135,17 @@ public class StaticTable implements Iterable<Entry>
|
|||
public static final int STATIC_SIZE = STATIC_TABLE.length - 1;
|
||||
|
||||
private final Map<HttpField, Entry> _staticFieldMap = new HashMap<>();
|
||||
private final Index<StaticEntry> _staticNameMap;
|
||||
private final StaticEntry[] _staticTableByHeader = new StaticEntry[HttpHeader.values().length];
|
||||
private final StaticEntry[] _staticTable = new StaticEntry[STATIC_TABLE.length];
|
||||
private final Index<Entry.StaticEntry> _staticNameMap;
|
||||
private final Entry.StaticEntry[] _staticTableByHeader = new Entry.StaticEntry[HttpHeader.values().length];
|
||||
private final Entry.StaticEntry[] _staticTable = new Entry.StaticEntry[STATIC_TABLE.length];
|
||||
|
||||
public StaticTable()
|
||||
{
|
||||
Index.Builder<StaticEntry> staticNameMapBuilder = new Index.Builder<StaticEntry>().caseSensitive(false);
|
||||
Index.Builder<Entry.StaticEntry> staticNameMapBuilder = new Index.Builder<Entry.StaticEntry>().caseSensitive(false);
|
||||
Set<String> added = new HashSet<>();
|
||||
for (int i = 0; i < STATIC_TABLE.length; i++)
|
||||
{
|
||||
StaticEntry entry = null;
|
||||
Entry.StaticEntry entry = null;
|
||||
|
||||
String name = STATIC_TABLE[i][0];
|
||||
String value = STATIC_TABLE[i][1];
|
||||
|
@ -159,7 +159,7 @@ public class StaticTable implements Iterable<Entry>
|
|||
|
||||
HttpMethod method = HttpMethod.CACHE.get(value);
|
||||
if (method != null)
|
||||
entry = new StaticEntry(i, new StaticTableHttpField(header, name, value, method));
|
||||
entry = new Entry.StaticEntry(i, new StaticTableHttpField(header, name, value, method));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -168,13 +168,13 @@ public class StaticTable implements Iterable<Entry>
|
|||
|
||||
HttpScheme scheme = HttpScheme.CACHE.get(value);
|
||||
if (scheme != null)
|
||||
entry = new StaticEntry(i, new StaticTableHttpField(header, name, value, scheme));
|
||||
entry = new Entry.StaticEntry(i, new StaticTableHttpField(header, name, value, scheme));
|
||||
break;
|
||||
}
|
||||
|
||||
case C_STATUS:
|
||||
{
|
||||
entry = new StaticEntry(i, new StaticTableHttpField(header, name, value, value));
|
||||
entry = new Entry.StaticEntry(i, new StaticTableHttpField(header, name, value, value));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ public class StaticTable implements Iterable<Entry>
|
|||
}
|
||||
|
||||
if (entry == null)
|
||||
entry = new StaticEntry(i, header == null ? new HttpField(STATIC_TABLE[i][0], value) : new HttpField(header, name, value));
|
||||
entry = new Entry.StaticEntry(i, header == null ? new HttpField(STATIC_TABLE[i][0], value) : new HttpField(header, name, value));
|
||||
|
||||
_staticTable[i] = entry;
|
||||
|
||||
|
@ -201,7 +201,7 @@ public class StaticTable implements Iterable<Entry>
|
|||
|
||||
for (HttpHeader h : HttpHeader.values())
|
||||
{
|
||||
StaticEntry entry = _staticNameMap.get(h.asString());
|
||||
Entry.StaticEntry entry = _staticNameMap.get(h.asString());
|
||||
if (entry != null)
|
||||
_staticTableByHeader[h.ordinal()] = entry;
|
||||
}
|
|
@ -11,11 +11,11 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal.unused;
|
||||
|
||||
import org.eclipse.jetty.http.HostPortHttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http3.qpack.table.StaticTable;
|
||||
import org.eclipse.jetty.http3.qpack.internal.table.StaticTable;
|
||||
|
||||
public class AuthorityHttpField extends HostPortHttpField
|
||||
{
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal.unused;
|
||||
|
||||
import org.eclipse.jetty.http.HostPortHttpField;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
|
@ -21,6 +21,7 @@ import org.eclipse.jetty.http.HttpMethod;
|
|||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.http3.qpack.QpackException.SessionException;
|
||||
|
||||
public class MetaDataBuilder
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal.unused;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.internal.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
||||
public class HuffmanDecoder
|
||||
{
|
||||
static final char EOS = HuffmanEncoder.EOS;
|
||||
static final char[] tree = HuffmanEncoder.tree;
|
||||
static final char[] rowsym = HuffmanEncoder.rowsym;
|
||||
static final byte[] rowbits = HuffmanEncoder.rowbits;
|
||||
|
||||
private final Utf8StringBuilder _utf8 = new Utf8StringBuilder();
|
||||
private int _length = 0;
|
||||
private int _count = 0;
|
||||
private int _node = 0;
|
||||
private int _current = 0;
|
||||
private int _bits = 0;
|
||||
|
||||
public void setLength(int length)
|
||||
{
|
||||
if (_count != 0)
|
||||
throw new IllegalStateException();
|
||||
_length = length;
|
||||
}
|
||||
|
||||
public String decode(ByteBuffer buffer) throws QpackException.CompressionException
|
||||
{
|
||||
for (; _count < _length; _count++)
|
||||
{
|
||||
if (!buffer.hasRemaining())
|
||||
return null;
|
||||
|
||||
int b = buffer.get() & 0xFF;
|
||||
_current = (_current << 8) | b;
|
||||
_bits += 8;
|
||||
while (_bits >= 8)
|
||||
{
|
||||
int c = (_current >>> (_bits - 8)) & 0xFF;
|
||||
_node = tree[_node * 256 + c];
|
||||
if (rowbits[_node] != 0)
|
||||
{
|
||||
if (rowsym[_node] == EOS)
|
||||
{
|
||||
reset();
|
||||
throw new QpackException.CompressionException("EOS in content");
|
||||
}
|
||||
|
||||
// terminal node
|
||||
_utf8.append((byte)(0xFF & rowsym[_node]));
|
||||
_bits -= rowbits[_node];
|
||||
_node = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-terminal node
|
||||
_bits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (_bits > 0)
|
||||
{
|
||||
int c = (_current << (8 - _bits)) & 0xFF;
|
||||
int lastNode = _node;
|
||||
_node = tree[_node * 256 + c];
|
||||
|
||||
if (rowbits[_node] == 0 || rowbits[_node] > _bits)
|
||||
{
|
||||
int requiredPadding = 0;
|
||||
for (int i = 0; i < _bits; i++)
|
||||
{
|
||||
requiredPadding = (requiredPadding << 1) | 1;
|
||||
}
|
||||
|
||||
if ((c >> (8 - _bits)) != requiredPadding)
|
||||
throw new QpackException.CompressionException("Incorrect padding");
|
||||
|
||||
_node = lastNode;
|
||||
break;
|
||||
}
|
||||
|
||||
_utf8.append((byte)(0xFF & rowsym[_node]));
|
||||
_bits -= rowbits[_node];
|
||||
_node = 0;
|
||||
}
|
||||
|
||||
if (_node != 0)
|
||||
{
|
||||
reset();
|
||||
throw new QpackException.CompressionException("Bad termination");
|
||||
}
|
||||
|
||||
String value = _utf8.toString();
|
||||
reset();
|
||||
return value;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
_utf8.reset();
|
||||
_count = 0;
|
||||
_current = 0;
|
||||
_node = 0;
|
||||
_bits = 0;
|
||||
}
|
||||
}
|
|
@ -11,13 +11,11 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
||||
public class Huffman
|
||||
public class HuffmanEncoder
|
||||
{
|
||||
|
||||
// Appendix C: Huffman Codes
|
||||
|
@ -348,77 +346,6 @@ public class Huffman
|
|||
}
|
||||
}
|
||||
|
||||
public static String decode(ByteBuffer buffer) throws QpackException.CompressionException
|
||||
{
|
||||
return decode(buffer, buffer.remaining());
|
||||
}
|
||||
|
||||
public static String decode(ByteBuffer buffer, int length) throws QpackException.CompressionException
|
||||
{
|
||||
Utf8StringBuilder utf8 = new Utf8StringBuilder(length * 2);
|
||||
int node = 0;
|
||||
int current = 0;
|
||||
int bits = 0;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
int b = buffer.get() & 0xFF;
|
||||
current = (current << 8) | b;
|
||||
bits += 8;
|
||||
while (bits >= 8)
|
||||
{
|
||||
int c = (current >>> (bits - 8)) & 0xFF;
|
||||
node = tree[node * 256 + c];
|
||||
if (rowbits[node] != 0)
|
||||
{
|
||||
if (rowsym[node] == EOS)
|
||||
throw new QpackException.CompressionException("EOS in content");
|
||||
|
||||
// terminal node
|
||||
utf8.append((byte)(0xFF & rowsym[node]));
|
||||
bits -= rowbits[node];
|
||||
node = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-terminal node
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (bits > 0)
|
||||
{
|
||||
int c = (current << (8 - bits)) & 0xFF;
|
||||
int lastNode = node;
|
||||
node = tree[node * 256 + c];
|
||||
|
||||
if (rowbits[node] == 0 || rowbits[node] > bits)
|
||||
{
|
||||
int requiredPadding = 0;
|
||||
for (int i = 0; i < bits; i++)
|
||||
{
|
||||
requiredPadding = (requiredPadding << 1) | 1;
|
||||
}
|
||||
|
||||
if ((c >> (8 - bits)) != requiredPadding)
|
||||
throw new QpackException.CompressionException("Incorrect padding");
|
||||
|
||||
node = lastNode;
|
||||
break;
|
||||
}
|
||||
|
||||
utf8.append((byte)(0xFF & rowsym[node]));
|
||||
bits -= rowbits[node];
|
||||
node = 0;
|
||||
}
|
||||
|
||||
if (node != 0)
|
||||
throw new QpackException.CompressionException("Bad termination");
|
||||
|
||||
return utf8.toString();
|
||||
}
|
||||
|
||||
public static int octetsNeeded(String s)
|
||||
{
|
||||
return octetsNeeded(CODES, s);
|
|
@ -11,11 +11,11 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
package org.eclipse.jetty.http3.qpack.internal.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class NBitInteger
|
||||
public class NBitIntegerEncoder
|
||||
{
|
||||
public static int octectsNeeded(int n, int i)
|
||||
{
|
||||
|
@ -101,46 +101,4 @@ public class NBitInteger
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int decode(ByteBuffer buffer, int n)
|
||||
{
|
||||
if (n == 8)
|
||||
{
|
||||
int nbits = 0xFF;
|
||||
|
||||
int i = buffer.get() & 0xff;
|
||||
|
||||
if (i == nbits)
|
||||
{
|
||||
int m = 1;
|
||||
int b;
|
||||
do
|
||||
{
|
||||
b = 0xff & buffer.get();
|
||||
i = i + (b & 127) * m;
|
||||
m = m * 128;
|
||||
}
|
||||
while ((b & 128) == 128);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int nbits = 0xFF >>> (8 - n);
|
||||
|
||||
int i = buffer.get(buffer.position() - 1) & nbits;
|
||||
|
||||
if (i == nbits)
|
||||
{
|
||||
int m = 1;
|
||||
int b;
|
||||
do
|
||||
{
|
||||
b = 0xff & buffer.get();
|
||||
i = i + (b & 127) * m;
|
||||
m = m * 128;
|
||||
}
|
||||
while ((b & 128) == 128);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.parser;
|
||||
package org.eclipse.jetty.http3.qpack.internal.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
|
@ -11,11 +11,10 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.parser;
|
||||
package org.eclipse.jetty.http3.qpack.internal.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.HuffmanDecoder;
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
|
||||
public class NBitStringParser
|
||||
|
@ -69,10 +68,11 @@ public class NBitStringParser
|
|||
if (_length < 0)
|
||||
return null;
|
||||
_state = State.VALUE;
|
||||
_huffmanBuilder.setLength(_length);
|
||||
continue;
|
||||
|
||||
case VALUE:
|
||||
String value = _huffman ? _huffmanBuilder.decode(buffer, _length) : asciiStringDecode(buffer);
|
||||
String value = _huffman ? _huffmanBuilder.decode(buffer) : asciiStringDecode(buffer);
|
||||
if (value != null)
|
||||
reset();
|
||||
return value;
|
|
@ -1,69 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http3.qpack.table;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http3.qpack.Huffman;
|
||||
import org.eclipse.jetty.http3.qpack.NBitInteger;
|
||||
|
||||
public class StaticEntry extends Entry
|
||||
{
|
||||
private final byte[] _huffmanValue;
|
||||
private final byte _encodedField;
|
||||
|
||||
StaticEntry(int index, HttpField field)
|
||||
{
|
||||
super(index, field);
|
||||
String value = field.getValue();
|
||||
if (value != null && value.length() > 0)
|
||||
{
|
||||
int huffmanLen = Huffman.octetsNeeded(value);
|
||||
if (huffmanLen < 0)
|
||||
throw new IllegalStateException("bad value");
|
||||
int lenLen = NBitInteger.octectsNeeded(7, huffmanLen);
|
||||
_huffmanValue = new byte[1 + lenLen + huffmanLen];
|
||||
ByteBuffer buffer = ByteBuffer.wrap(_huffmanValue);
|
||||
|
||||
// Indicate Huffman
|
||||
buffer.put((byte)0x80);
|
||||
// Add huffman length
|
||||
NBitInteger.encode(buffer, 7, huffmanLen);
|
||||
// Encode value
|
||||
Huffman.encode(buffer, value);
|
||||
}
|
||||
else
|
||||
_huffmanValue = null;
|
||||
|
||||
_encodedField = (byte)(0x80 | index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getStaticHuffmanValue()
|
||||
{
|
||||
return _huffmanValue;
|
||||
}
|
||||
|
||||
public byte getEncodedField()
|
||||
{
|
||||
return _encodedField;
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ import java.nio.ByteBuffer;
|
|||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.parser.DecoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.parser.DecoderInstructionParser;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
|
|
@ -17,14 +17,13 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http3.qpack.generator.IndexedNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.InsertCountIncrementInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.LiteralNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.SectionAcknowledgmentInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.SetCapacityInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.parser.DecoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.parser.EncoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.IndexedNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.InsertCountIncrementInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.LiteralNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.SectionAcknowledgmentInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.SetCapacityInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.parser.DecoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.parser.EncoderInstructionParser;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
|
@ -17,7 +17,7 @@ import java.nio.ByteBuffer;
|
|||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.parser.EncoderInstructionParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.parser.EncoderInstructionParser;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
|
|
@ -18,6 +18,8 @@ import java.nio.ByteBuffer;
|
|||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.HuffmanDecoder;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.HuffmanEncoder;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
|
@ -51,7 +53,9 @@ public class HuffmanTest
|
|||
public void testDecode(String specSection, String hex, String expected) throws Exception
|
||||
{
|
||||
byte[] encoded = TypeUtil.fromHexString(hex);
|
||||
String decoded = Huffman.decode(ByteBuffer.wrap(encoded));
|
||||
HuffmanDecoder huffmanDecoder = new HuffmanDecoder();
|
||||
huffmanDecoder.setLength(encoded.length);
|
||||
String decoded = huffmanDecoder.decode(ByteBuffer.wrap(encoded));
|
||||
assertEquals(expected, decoded, specSection);
|
||||
}
|
||||
|
||||
|
@ -61,11 +65,11 @@ public class HuffmanTest
|
|||
{
|
||||
ByteBuffer buf = BufferUtil.allocate(1024);
|
||||
int pos = BufferUtil.flipToFill(buf);
|
||||
Huffman.encode(buf, expected);
|
||||
HuffmanEncoder.encode(buf, expected);
|
||||
BufferUtil.flipToFlush(buf, pos);
|
||||
String encoded = TypeUtil.toHexString(BufferUtil.toArray(buf)).toLowerCase(Locale.ENGLISH);
|
||||
assertEquals(hex, encoded, specSection);
|
||||
assertEquals(hex.length() / 2, Huffman.octetsNeeded(expected));
|
||||
assertEquals(hex.length() / 2, HuffmanEncoder.octetsNeeded(expected));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "[{index}]") // don't include unprintable character in test display-name
|
||||
|
@ -74,9 +78,9 @@ public class HuffmanTest
|
|||
{
|
||||
String s = "bad '" + bad + "'";
|
||||
|
||||
assertThat(Huffman.octetsNeeded(s), Matchers.is(-1));
|
||||
assertThat(HuffmanEncoder.octetsNeeded(s), Matchers.is(-1));
|
||||
|
||||
assertThrows(BufferOverflowException.class,
|
||||
() -> Huffman.encode(BufferUtil.allocate(32), s));
|
||||
() -> HuffmanEncoder.encode(BufferUtil.allocate(32), s));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
|
||||
package org.eclipse.jetty.http3.qpack;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.generator.IndexedNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.Instruction;
|
||||
import org.eclipse.jetty.http3.qpack.generator.SectionAcknowledgmentInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.IndexedNameEntryInstruction;
|
||||
import org.eclipse.jetty.http3.qpack.internal.instruction.SectionAcknowledgmentInstruction;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
|
|
@ -15,7 +15,7 @@ package org.eclipse.jetty.http3.qpack;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.parser.NBitIntegerParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
|
@ -15,6 +15,8 @@ package org.eclipse.jetty.http3.qpack;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -24,21 +26,22 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
@SuppressWarnings("PointlessArithmeticExpression")
|
||||
public class NBitIntegerTest
|
||||
{
|
||||
private final NBitIntegerParser _parser = new NBitIntegerParser();
|
||||
|
||||
@Test
|
||||
public void testOctetsNeeded()
|
||||
{
|
||||
assertEquals(0, NBitInteger.octectsNeeded(5, 10));
|
||||
assertEquals(2, NBitInteger.octectsNeeded(5, 1337));
|
||||
assertEquals(1, NBitInteger.octectsNeeded(8, 42));
|
||||
assertEquals(3, NBitInteger.octectsNeeded(8, 1337));
|
||||
assertEquals(0, NBitIntegerEncoder.octectsNeeded(5, 10));
|
||||
assertEquals(2, NBitIntegerEncoder.octectsNeeded(5, 1337));
|
||||
assertEquals(1, NBitIntegerEncoder.octectsNeeded(8, 42));
|
||||
assertEquals(3, NBitIntegerEncoder.octectsNeeded(8, 1337));
|
||||
|
||||
assertEquals(0, NBitInteger.octectsNeeded(6, 62));
|
||||
assertEquals(1, NBitInteger.octectsNeeded(6, 63));
|
||||
assertEquals(1, NBitInteger.octectsNeeded(6, 64));
|
||||
assertEquals(2, NBitInteger.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x01));
|
||||
assertEquals(3, NBitInteger.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80));
|
||||
assertEquals(4, NBitInteger.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80 * 0x80));
|
||||
assertEquals(0, NBitIntegerEncoder.octectsNeeded(6, 62));
|
||||
assertEquals(1, NBitIntegerEncoder.octectsNeeded(6, 63));
|
||||
assertEquals(1, NBitIntegerEncoder.octectsNeeded(6, 64));
|
||||
assertEquals(2, NBitIntegerEncoder.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x01));
|
||||
assertEquals(3, NBitIntegerEncoder.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80));
|
||||
assertEquals(4, NBitIntegerEncoder.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80 * 0x80));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -79,12 +82,12 @@ public class NBitIntegerTest
|
|||
int p = BufferUtil.flipToFill(buf);
|
||||
if (n < 8)
|
||||
buf.put((byte)0x00);
|
||||
NBitInteger.encode(buf, n, i);
|
||||
NBitIntegerEncoder.encode(buf, n, i);
|
||||
BufferUtil.flipToFlush(buf, p);
|
||||
String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
|
||||
assertEquals(expected, r);
|
||||
|
||||
assertEquals(expected.length() / 2, (n < 8 ? 1 : 0) + NBitInteger.octectsNeeded(n, i));
|
||||
assertEquals(expected.length() / 2, (n < 8 ? 1 : 0) + NBitIntegerEncoder.octectsNeeded(n, i));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -122,8 +125,8 @@ public class NBitIntegerTest
|
|||
public void testDecode(int n, int expected, String encoded)
|
||||
{
|
||||
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
|
||||
buf.position(n == 8 ? 0 : 1);
|
||||
assertEquals(expected, NBitInteger.decode(buf, n));
|
||||
_parser.setPrefix(n);
|
||||
assertEquals(expected, _parser.decode(buf));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -133,7 +136,7 @@ public class NBitIntegerTest
|
|||
int p = BufferUtil.flipToFill(buf);
|
||||
buf.put((byte)0x77);
|
||||
buf.put((byte)0xFF);
|
||||
NBitInteger.encode(buf, 5, 10);
|
||||
NBitIntegerEncoder.encode(buf, 5, 10);
|
||||
BufferUtil.flipToFlush(buf, p);
|
||||
|
||||
String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
|
||||
|
@ -145,9 +148,9 @@ public class NBitIntegerTest
|
|||
public void testDecodeExampleD11()
|
||||
{
|
||||
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("77EaFF"));
|
||||
buf.position(2);
|
||||
|
||||
assertEquals(10, NBitInteger.decode(buf, 5));
|
||||
buf.position(1);
|
||||
_parser.setPrefix(5);
|
||||
assertEquals(10, _parser.decode(buf));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -157,7 +160,7 @@ public class NBitIntegerTest
|
|||
int p = BufferUtil.flipToFill(buf);
|
||||
buf.put((byte)0x88);
|
||||
buf.put((byte)0x00);
|
||||
NBitInteger.encode(buf, 5, 1337);
|
||||
NBitIntegerEncoder.encode(buf, 5, 1337);
|
||||
BufferUtil.flipToFlush(buf, p);
|
||||
|
||||
String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
|
||||
|
@ -169,9 +172,9 @@ public class NBitIntegerTest
|
|||
public void testDecodeExampleD12()
|
||||
{
|
||||
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("881f9a0aff"));
|
||||
buf.position(2);
|
||||
|
||||
assertEquals(1337, NBitInteger.decode(buf, 5));
|
||||
buf.position(1);
|
||||
_parser.setPrefix(5);
|
||||
assertEquals(1337, _parser.decode(buf));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -181,7 +184,7 @@ public class NBitIntegerTest
|
|||
int p = BufferUtil.flipToFill(buf);
|
||||
buf.put((byte)0x88);
|
||||
buf.put((byte)0xFF);
|
||||
NBitInteger.encode(buf, 8, 42);
|
||||
NBitIntegerEncoder.encode(buf, 8, 42);
|
||||
BufferUtil.flipToFlush(buf, p);
|
||||
|
||||
String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
|
||||
|
@ -194,7 +197,7 @@ public class NBitIntegerTest
|
|||
{
|
||||
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("882aFf"));
|
||||
buf.position(1);
|
||||
|
||||
assertEquals(42, NBitInteger.decode(buf, 8));
|
||||
_parser.setPrefix(8);
|
||||
assertEquals(42, _parser.decode(buf));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ package org.eclipse.jetty.http3.qpack;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.generator.Instruction;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.NullByteBufferPool;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
|
|
@ -17,7 +17,6 @@ import java.util.LinkedList;
|
|||
import java.util.Queue;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http3.qpack.generator.Instruction;
|
||||
|
||||
public class TestDecoderHandler implements QpackDecoder.Handler
|
||||
{
|
||||
|
|
|
@ -16,8 +16,6 @@ package org.eclipse.jetty.http3.qpack;
|
|||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.generator.Instruction;
|
||||
|
||||
public class TestEncoderHandler implements QpackEncoder.Handler
|
||||
{
|
||||
private final Queue<Instruction> _instructionList = new LinkedList<>();
|
||||
|
|
Loading…
Reference in New Issue