Refactor QPACK to use an internal package for non API classes.

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2021-03-10 12:22:05 +11:00 committed by Simone Bordet
parent f9606770b3
commit ea70f599bb
41 changed files with 385 additions and 483 deletions

View File

@ -17,9 +17,6 @@ import org.eclipse.jetty.http3.qpack.QpackFieldPreEncoder;
module org.eclipse.jetty.http3.qpack module org.eclipse.jetty.http3.qpack
{ {
exports 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 transitive org.eclipse.jetty.http;
requires org.slf4j; requires org.slf4j;

View File

@ -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;
}
}

View File

@ -11,7 +11,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;

View File

@ -21,15 +21,15 @@ import java.util.List;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http3.qpack.generator.InsertCountIncrementInstruction; import org.eclipse.jetty.http3.qpack.internal.QpackContext;
import org.eclipse.jetty.http3.qpack.generator.Instruction; import org.eclipse.jetty.http3.qpack.internal.instruction.InsertCountIncrementInstruction;
import org.eclipse.jetty.http3.qpack.generator.SectionAcknowledgmentInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.SectionAcknowledgmentInstruction;
import org.eclipse.jetty.http3.qpack.parser.DecoderInstructionParser; import org.eclipse.jetty.http3.qpack.internal.parser.DecoderInstructionParser;
import org.eclipse.jetty.http3.qpack.parser.EncodedFieldSection; import org.eclipse.jetty.http3.qpack.internal.parser.EncodedFieldSection;
import org.eclipse.jetty.http3.qpack.parser.NBitIntegerParser; import org.eclipse.jetty.http3.qpack.internal.table.DynamicTable;
import org.eclipse.jetty.http3.qpack.table.DynamicTable; import org.eclipse.jetty.http3.qpack.internal.table.Entry;
import org.eclipse.jetty.http3.qpack.table.Entry; import org.eclipse.jetty.http3.qpack.internal.table.StaticTable;
import org.eclipse.jetty.http3.qpack.table.StaticTable; import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.Dumpable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -46,7 +46,6 @@ public class QpackDecoder implements Dumpable
private final Handler _handler; private final Handler _handler;
private final QpackContext _context; private final QpackContext _context;
private final MetaDataBuilder _builder;
private final DecoderInstructionParser _parser; private final DecoderInstructionParser _parser;
private final List<EncodedFieldSection> _encodedFieldSections = new ArrayList<>(); private final List<EncodedFieldSection> _encodedFieldSections = new ArrayList<>();
@ -58,12 +57,11 @@ public class QpackDecoder implements Dumpable
public QpackDecoder(Handler handler, int maxHeaderSize) public QpackDecoder(Handler handler, int maxHeaderSize)
{ {
_context = new QpackContext(); _context = new QpackContext();
_builder = new MetaDataBuilder(maxHeaderSize);
_handler = handler; _handler = handler;
_parser = new DecoderInstructionParser(new DecoderAdapter()); _parser = new DecoderInstructionParser(new DecoderAdapter());
} }
public QpackContext getQpackContext() QpackContext getQpackContext()
{ {
return _context; return _context;
} }
@ -83,8 +81,8 @@ public class QpackDecoder implements Dumpable
LOG.debug(String.format("CtxTbl[%x] decoding %d octets", _context.hashCode(), buffer.remaining())); 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 the buffer is big, don't even think about decoding it
if (buffer.remaining() > _builder.getMaxSize()) // if (buffer.remaining() > _builder.getMaxSize())
throw new QpackException.SessionException("431 Request Header Fields too large"); //throw new QpackException.SessionException("431 Request Header Fields too large");
_integerDecoder.setPrefix(8); _integerDecoder.setPrefix(8);
int encodedInsertCount = _integerDecoder.decode(buffer); int encodedInsertCount = _integerDecoder.decode(buffer);
@ -235,6 +233,9 @@ public class QpackDecoder implements Dumpable
return String.format("QpackDecoder@%x{%s}", hashCode(), _context); return String.format("QpackDecoder@%x{%s}", hashCode(), _context);
} }
/**
* This delivers notifications from the DecoderInstruction parser directly into the Decoder.
*/
class DecoderAdapter implements DecoderInstructionParser.Handler class DecoderAdapter implements DecoderInstructionParser.Handler
{ {
@Override @Override

View File

@ -28,14 +28,17 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http3.qpack.generator.DuplicateInstruction; import org.eclipse.jetty.http3.qpack.internal.EncodableEntry;
import org.eclipse.jetty.http3.qpack.generator.IndexedNameEntryInstruction; import org.eclipse.jetty.http3.qpack.internal.QpackContext;
import org.eclipse.jetty.http3.qpack.generator.Instruction; import org.eclipse.jetty.http3.qpack.internal.StreamInfo;
import org.eclipse.jetty.http3.qpack.generator.LiteralNameEntryInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.DuplicateInstruction;
import org.eclipse.jetty.http3.qpack.generator.SetCapacityInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.IndexedNameEntryInstruction;
import org.eclipse.jetty.http3.qpack.parser.EncoderInstructionParser; import org.eclipse.jetty.http3.qpack.internal.instruction.LiteralNameEntryInstruction;
import org.eclipse.jetty.http3.qpack.table.DynamicTable; import org.eclipse.jetty.http3.qpack.internal.instruction.SetCapacityInstruction;
import org.eclipse.jetty.http3.qpack.table.Entry; 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.ByteBufferPool;
import org.eclipse.jetty.io.NullByteBufferPool; import org.eclipse.jetty.io.NullByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -126,7 +129,7 @@ public class QpackEncoder implements Dumpable
_parser = new EncoderInstructionParser(new EncoderAdapter()); _parser = new EncoderInstructionParser(new EncoderAdapter());
} }
public QpackContext getQpackContext() QpackContext getQpackContext()
{ {
return _context; 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? // Calculate the size required. TODO: it may be more efficient to just use a buffer of MAX_HEADER_SIZE?
int spaceRequired = 0; int spaceRequired = 0;
spaceRequired += 1 + NBitInteger.octectsNeeded(8, encodedInsertCount); spaceRequired += 1 + NBitIntegerEncoder.octectsNeeded(8, encodedInsertCount);
spaceRequired += 1 + NBitInteger.octectsNeeded(7, deltaBase); spaceRequired += 1 + NBitIntegerEncoder.octectsNeeded(7, deltaBase);
for (EncodableEntry encodableEntry : encodableEntries) for (EncodableEntry encodableEntry : encodableEntries)
{ {
spaceRequired += encodableEntry.getRequiredSize(base); spaceRequired += encodableEntry.getRequiredSize(base);
@ -313,9 +316,9 @@ public class QpackEncoder implements Dumpable
int pos = BufferUtil.flipToFill(buffer); int pos = BufferUtil.flipToFill(buffer);
// Encode the Field Section Prefix into the ByteBuffer. // 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); buffer.put(signBit ? (byte)0x80 : (byte)0x00);
NBitInteger.encode(buffer, 7, deltaBase); NBitIntegerEncoder.encode(buffer, 7, deltaBase);
// Encode the field lines into the ByteBuffer. // Encode the field lines into the ByteBuffer.
for (EncodableEntry entry : encodableEntries) for (EncodableEntry entry : encodableEntries)

View File

@ -19,8 +19,10 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFieldPreEncoder; import org.eclipse.jetty.http.HttpFieldPreEncoder;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http3.qpack.table.Entry; import org.eclipse.jetty.http3.qpack.internal.EncodableEntry;
import org.eclipse.jetty.http3.qpack.table.StaticTable; 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; import org.eclipse.jetty.util.BufferUtil;
public class QpackFieldPreEncoder implements HttpFieldPreEncoder public class QpackFieldPreEncoder implements HttpFieldPreEncoder

View File

@ -11,7 +11,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack; package org.eclipse.jetty.http3.qpack.internal;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Objects; import java.util.Objects;
@ -19,35 +19,37 @@ import java.util.Objects;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.PreEncodedHttpField; 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); 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); 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); return new LiteralEntry(field, huffman);
} }
static EncodableEntry getPreEncodedEntry(PreEncodedHttpField httpField) public static EncodableEntry getPreEncodedEntry(PreEncodedHttpField httpField)
{ {
return new PreEncodedEntry(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 private static class ReferencedEntry extends EncodableEntry
{ {
@ -67,21 +69,21 @@ abstract class EncodableEntry
// Indexed Field Line with Static Reference. // Indexed Field Line with Static Reference.
buffer.put((byte)(0x80 | 0x40)); buffer.put((byte)(0x80 | 0x40));
int relativeIndex = _entry.getIndex(); int relativeIndex = _entry.getIndex();
NBitInteger.encode(buffer, 6, relativeIndex); NBitIntegerEncoder.encode(buffer, 6, relativeIndex);
} }
else if (_entry.getIndex() < base) else if (_entry.getIndex() < base)
{ {
// Indexed Field Line with Dynamic Reference. // Indexed Field Line with Dynamic Reference.
buffer.put((byte)0x80); buffer.put((byte)0x80);
int relativeIndex = base - (_entry.getIndex() + 1); int relativeIndex = base - (_entry.getIndex() + 1);
NBitInteger.encode(buffer, 6, relativeIndex); NBitIntegerEncoder.encode(buffer, 6, relativeIndex);
} }
else else
{ {
// Indexed Field Line with Post-Base Index. // Indexed Field Line with Post-Base Index.
buffer.put((byte)0x10); buffer.put((byte)0x10);
int relativeIndex = _entry.getIndex() - base; 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. // Indexed Field Line with Static Reference.
int relativeIndex = _entry.getIndex(); int relativeIndex = _entry.getIndex();
return 1 + NBitInteger.octectsNeeded(6, relativeIndex); return 1 + NBitIntegerEncoder.octectsNeeded(6, relativeIndex);
} }
else if (_entry.getIndex() < base) else if (_entry.getIndex() < base)
{ {
// Indexed Field Line with Dynamic Reference. // Indexed Field Line with Dynamic Reference.
int relativeIndex = base - (_entry.getIndex() + 1); int relativeIndex = base - (_entry.getIndex() + 1);
return 1 + NBitInteger.octectsNeeded(6, relativeIndex); return 1 + NBitIntegerEncoder.octectsNeeded(6, relativeIndex);
} }
else else
{ {
// Indexed Field Line with Post-Base Index. // Indexed Field Line with Post-Base Index.
int relativeIndex = _entry.getIndex() - base; 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. // Literal Field Line with Static Name Reference.
buffer.put((byte)(0x40 | allowIntermediary | 0x10)); buffer.put((byte)(0x40 | allowIntermediary | 0x10));
int relativeIndex = _nameEntry.getIndex(); int relativeIndex = _nameEntry.getIndex();
NBitInteger.encode(buffer, 4, relativeIndex); NBitIntegerEncoder.encode(buffer, 4, relativeIndex);
} }
else if (_nameEntry.getIndex() < base) else if (_nameEntry.getIndex() < base)
{ {
// Literal Field Line with Dynamic Name Reference. // Literal Field Line with Dynamic Name Reference.
buffer.put((byte)(0x40 | allowIntermediary)); buffer.put((byte)(0x40 | allowIntermediary));
int relativeIndex = base - (_nameEntry.getIndex() + 1); int relativeIndex = base - (_nameEntry.getIndex() + 1);
NBitInteger.encode(buffer, 4, relativeIndex); NBitIntegerEncoder.encode(buffer, 4, relativeIndex);
} }
else else
{ {
// Literal Field Line with Post-Base Name Reference. // Literal Field Line with Post-Base Name Reference.
buffer.put(allowIntermediary); buffer.put(allowIntermediary);
int relativeIndex = _nameEntry.getIndex() - base; int relativeIndex = _nameEntry.getIndex() - base;
NBitInteger.encode(buffer, 3, relativeIndex); NBitIntegerEncoder.encode(buffer, 3, relativeIndex);
} }
// Encode the value. // Encode the value.
@ -165,13 +167,13 @@ abstract class EncodableEntry
if (_huffman) if (_huffman)
{ {
buffer.put((byte)0x80); buffer.put((byte)0x80);
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(value)); NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(value));
Huffman.encode(buffer, value); HuffmanEncoder.encode(buffer, value);
} }
else else
{ {
buffer.put((byte)0x00); buffer.put((byte)0x00);
NBitInteger.encode(buffer, 7, value.length()); NBitIntegerEncoder.encode(buffer, 7, value.length());
buffer.put(value.getBytes()); buffer.put(value.getBytes());
} }
} }
@ -181,8 +183,8 @@ abstract class EncodableEntry
{ {
String value = getValue(); String value = getValue();
int relativeIndex = _nameEntry.getIndex() - base; int relativeIndex = _nameEntry.getIndex() - base;
int valueLength = _huffman ? Huffman.octetsNeeded(value) : value.length(); int valueLength = _huffman ? HuffmanEncoder.octetsNeeded(value) : value.length();
return 1 + NBitInteger.octectsNeeded(4, relativeIndex) + 1 + NBitInteger.octectsNeeded(7, valueLength) + valueLength; return 1 + NBitIntegerEncoder.octectsNeeded(4, relativeIndex) + 1 + NBitIntegerEncoder.octectsNeeded(7, valueLength) + valueLength;
} }
@Override @Override
@ -220,20 +222,20 @@ abstract class EncodableEntry
if (_huffman) if (_huffman)
{ {
buffer.put((byte)(0x28 | allowIntermediary)); buffer.put((byte)(0x28 | allowIntermediary));
NBitInteger.encode(buffer, 3, Huffman.octetsNeeded(name)); NBitIntegerEncoder.encode(buffer, 3, HuffmanEncoder.octetsNeeded(name));
Huffman.encode(buffer, name); HuffmanEncoder.encode(buffer, name);
buffer.put((byte)0x80); buffer.put((byte)0x80);
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(value)); NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(value));
Huffman.encode(buffer, value); HuffmanEncoder.encode(buffer, value);
} }
else else
{ {
// TODO: What charset should we be using? (this applies to the instruction generators as well). // TODO: What charset should we be using? (this applies to the instruction generators as well).
buffer.put((byte)(0x20 | allowIntermediary)); buffer.put((byte)(0x20 | allowIntermediary));
NBitInteger.encode(buffer, 3, name.length()); NBitIntegerEncoder.encode(buffer, 3, name.length());
buffer.put(name.getBytes()); buffer.put(name.getBytes());
buffer.put((byte)0x00); buffer.put((byte)0x00);
NBitInteger.encode(buffer, 7, value.length()); NBitIntegerEncoder.encode(buffer, 7, value.length());
buffer.put(value.getBytes()); buffer.put(value.getBytes());
} }
} }
@ -243,9 +245,9 @@ abstract class EncodableEntry
{ {
String name = getName(); String name = getName();
String value = getValue(); String value = getValue();
int nameLength = _huffman ? Huffman.octetsNeeded(name) : name.length(); int nameLength = _huffman ? HuffmanEncoder.octetsNeeded(name) : name.length();
int valueLength = _huffman ? Huffman.octetsNeeded(value) : value.length(); int valueLength = _huffman ? HuffmanEncoder.octetsNeeded(value) : value.length();
return 2 + NBitInteger.octectsNeeded(3, nameLength) + nameLength + NBitInteger.octectsNeeded(7, valueLength) + valueLength; return 2 + NBitIntegerEncoder.octectsNeeded(3, nameLength) + nameLength + NBitIntegerEncoder.octectsNeeded(7, valueLength) + valueLength;
} }
@Override @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 static class PreEncodedEntry extends EncodableEntry
{ {
private final PreEncodedHttpField _httpField; private final PreEncodedHttpField _httpField;

View File

@ -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.http.HttpField;
import org.eclipse.jetty.http3.qpack.table.DynamicTable; import org.eclipse.jetty.http3.qpack.internal.table.DynamicTable;
import org.eclipse.jetty.http3.qpack.table.Entry; import org.eclipse.jetty.http3.qpack.internal.table.Entry;
import org.eclipse.jetty.http3.qpack.table.StaticTable; import org.eclipse.jetty.http3.qpack.internal.table.StaticTable;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -11,7 +11,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack; package org.eclipse.jetty.http3.qpack.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -19,9 +19,9 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue; 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 int _streamId;
private final Queue<SectionInfo> _sectionInfos = new LinkedList<>(); private final Queue<SectionInfo> _sectionInfos = new LinkedList<>();

View File

@ -11,11 +11,12 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack.internal.instruction;
import java.nio.ByteBuffer; 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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -36,10 +37,10 @@ public class DuplicateInstruction implements Instruction
@Override @Override
public void encode(ByteBufferPool.Lease lease) 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); ByteBuffer buffer = lease.acquire(size, false);
buffer.put((byte)0x00); buffer.put((byte)0x00);
NBitInteger.encode(buffer, 5, _index); NBitIntegerEncoder.encode(buffer, 5, _index);
BufferUtil.flipToFlush(buffer, 0); BufferUtil.flipToFlush(buffer, 0);
lease.append(buffer, true); lease.append(buffer, true);
} }

View File

@ -11,12 +11,13 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack.internal.instruction;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http3.qpack.Huffman; import org.eclipse.jetty.http3.qpack.Instruction;
import org.eclipse.jetty.http3.qpack.NBitInteger; 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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -53,24 +54,24 @@ public class IndexedNameEntryInstruction implements Instruction
@Override @Override
public void encode(ByteBufferPool.Lease lease) 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); ByteBuffer buffer = lease.acquire(size, false);
// First bit indicates the instruction, second bit is whether it is a dynamic table reference or not. // First bit indicates the instruction, second bit is whether it is a dynamic table reference or not.
buffer.put((byte)(0x80 | (_dynamic ? 0x00 : 0x40))); buffer.put((byte)(0x80 | (_dynamic ? 0x00 : 0x40)));
NBitInteger.encode(buffer, 6, _index); NBitIntegerEncoder.encode(buffer, 6, _index);
// We will not huffman encode the string. // We will not huffman encode the string.
if (_huffman) if (_huffman)
{ {
buffer.put((byte)(0x80)); buffer.put((byte)(0x80));
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(_value)); NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(_value));
Huffman.encode(buffer, _value); HuffmanEncoder.encode(buffer, _value);
} }
else else
{ {
buffer.put((byte)(0x00)); buffer.put((byte)(0x00));
NBitInteger.encode(buffer, 7, _value.length()); NBitIntegerEncoder.encode(buffer, 7, _value.length());
buffer.put(_value.getBytes()); buffer.put(_value.getBytes());
} }

View File

@ -11,11 +11,12 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack.internal.instruction;
import java.nio.ByteBuffer; 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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -31,10 +32,10 @@ public class InsertCountIncrementInstruction implements Instruction
@Override @Override
public void encode(ByteBufferPool.Lease lease) 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); ByteBuffer buffer = lease.acquire(size, false);
buffer.put((byte)0x00); buffer.put((byte)0x00);
NBitInteger.encode(buffer, 6, _increment); NBitIntegerEncoder.encode(buffer, 6, _increment);
BufferUtil.flipToFlush(buffer, 0); BufferUtil.flipToFlush(buffer, 0);
lease.append(buffer, true); lease.append(buffer, true);
} }

View File

@ -11,12 +11,13 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack.internal.instruction;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http3.qpack.Huffman; import org.eclipse.jetty.http3.qpack.Instruction;
import org.eclipse.jetty.http3.qpack.NBitInteger; 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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -48,33 +49,33 @@ public class LiteralNameEntryInstruction implements Instruction
@Override @Override
public void encode(ByteBufferPool.Lease lease) public void encode(ByteBufferPool.Lease lease)
{ {
int size = (_huffmanName ? Huffman.octetsNeeded(_name) : _name.length()) + int size = (_huffmanName ? HuffmanEncoder.octetsNeeded(_name) : _name.length()) +
(_huffmanValue ? Huffman.octetsNeeded(_value) : _value.length()) + 2; (_huffmanValue ? HuffmanEncoder.octetsNeeded(_value) : _value.length()) + 2;
ByteBuffer buffer = lease.acquire(size, false); ByteBuffer buffer = lease.acquire(size, false);
if (_huffmanName) if (_huffmanName)
{ {
buffer.put((byte)(0x40 | 0x20)); buffer.put((byte)(0x40 | 0x20));
NBitInteger.encode(buffer, 5, Huffman.octetsNeeded(_name)); NBitIntegerEncoder.encode(buffer, 5, HuffmanEncoder.octetsNeeded(_name));
Huffman.encode(buffer, _name); HuffmanEncoder.encode(buffer, _name);
} }
else else
{ {
buffer.put((byte)(0x40)); buffer.put((byte)(0x40));
NBitInteger.encode(buffer, 5, _name.length()); NBitIntegerEncoder.encode(buffer, 5, _name.length());
buffer.put(_name.getBytes()); buffer.put(_name.getBytes());
} }
if (_huffmanValue) if (_huffmanValue)
{ {
buffer.put((byte)(0x80)); buffer.put((byte)(0x80));
NBitInteger.encode(buffer, 7, Huffman.octetsNeeded(_value)); NBitIntegerEncoder.encode(buffer, 7, HuffmanEncoder.octetsNeeded(_value));
Huffman.encode(buffer, _value); HuffmanEncoder.encode(buffer, _value);
} }
else else
{ {
buffer.put((byte)(0x00)); buffer.put((byte)(0x00));
NBitInteger.encode(buffer, 5, _value.length()); NBitIntegerEncoder.encode(buffer, 5, _value.length());
buffer.put(_value.getBytes()); buffer.put(_value.getBytes());
} }

View File

@ -11,11 +11,12 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack.internal.instruction;
import java.nio.ByteBuffer; 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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -31,10 +32,10 @@ public class SectionAcknowledgmentInstruction implements Instruction
@Override @Override
public void encode(ByteBufferPool.Lease lease) 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); ByteBuffer buffer = lease.acquire(size, false);
buffer.put((byte)0x80); buffer.put((byte)0x80);
NBitInteger.encode(buffer, 7, _streamId); NBitIntegerEncoder.encode(buffer, 7, _streamId);
BufferUtil.flipToFlush(buffer, 0); BufferUtil.flipToFlush(buffer, 0);
lease.append(buffer, true); lease.append(buffer, true);
} }

View File

@ -11,11 +11,12 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack.internal.instruction;
import java.nio.ByteBuffer; 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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -36,10 +37,10 @@ public class SetCapacityInstruction implements Instruction
@Override @Override
public void encode(ByteBufferPool.Lease lease) 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); ByteBuffer buffer = lease.acquire(size, false);
buffer.put((byte)0x20); buffer.put((byte)0x20);
NBitInteger.encode(buffer, 5, _capacity); NBitIntegerEncoder.encode(buffer, 5, _capacity);
BufferUtil.flipToFlush(buffer, 0); BufferUtil.flipToFlush(buffer, 0);
lease.append(buffer, true); lease.append(buffer, true);
} }

View File

@ -11,11 +11,12 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.generator; package org.eclipse.jetty.http3.qpack.internal.instruction;
import java.nio.ByteBuffer; 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.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -31,10 +32,10 @@ public class StreamCancellationInstruction implements Instruction
@Override @Override
public void encode(ByteBufferPool.Lease lease) 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); ByteBuffer buffer = lease.acquire(size, false);
buffer.put((byte)0x40); buffer.put((byte)0x40);
NBitInteger.encode(buffer, 6, _streamId); NBitIntegerEncoder.encode(buffer, 6, _streamId);
BufferUtil.flipToFlush(buffer, 0); BufferUtil.flipToFlush(buffer, 0);
lease.append(buffer, true); lease.append(buffer, true);
} }

View File

@ -11,11 +11,13 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.parser; package org.eclipse.jetty.http3.qpack.internal.parser;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http3.qpack.QpackException; 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. * Parses a stream of unframed instructions for the Decoder. These instructions are sent from the remote Encoder.

View File

@ -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.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,8 +19,10 @@ import java.util.List;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields; 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.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 public class EncodedFieldSection
{ {

View File

@ -11,11 +11,12 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.parser; package org.eclipse.jetty.http3.qpack.internal.parser;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http3.qpack.QpackException; 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. * Parses a stream of unframed instructions for the Encoder. These instructions are sent from the remote Decoder.

View File

@ -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.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -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 java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.http.HttpField; 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; import org.eclipse.jetty.util.StringUtil;
public class Entry public class Entry
@ -88,7 +91,7 @@ public class Entry
@Override @Override
public String toString() 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); _absoluteIndex, _referenceCount.get(), _field);
} }
@ -101,4 +104,53 @@ public class Entry
{ {
return 32 + StringUtil.getLength(field.getName()) + StringUtil.getLength(field.getValue()); 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;
}
}
} }

View File

@ -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.Arrays;
import java.util.HashMap; 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.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme; 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; import org.eclipse.jetty.util.Index;
public class StaticTable implements Iterable<Entry> 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; public static final int STATIC_SIZE = STATIC_TABLE.length - 1;
private final Map<HttpField, Entry> _staticFieldMap = new HashMap<>(); private final Map<HttpField, Entry> _staticFieldMap = new HashMap<>();
private final Index<StaticEntry> _staticNameMap; private final Index<Entry.StaticEntry> _staticNameMap;
private final StaticEntry[] _staticTableByHeader = new StaticEntry[HttpHeader.values().length]; private final Entry.StaticEntry[] _staticTableByHeader = new Entry.StaticEntry[HttpHeader.values().length];
private final StaticEntry[] _staticTable = new StaticEntry[STATIC_TABLE.length]; private final Entry.StaticEntry[] _staticTable = new Entry.StaticEntry[STATIC_TABLE.length];
public StaticTable() 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<>(); Set<String> added = new HashSet<>();
for (int i = 0; i < STATIC_TABLE.length; i++) for (int i = 0; i < STATIC_TABLE.length; i++)
{ {
StaticEntry entry = null; Entry.StaticEntry entry = null;
String name = STATIC_TABLE[i][0]; String name = STATIC_TABLE[i][0];
String value = STATIC_TABLE[i][1]; String value = STATIC_TABLE[i][1];
@ -159,7 +159,7 @@ public class StaticTable implements Iterable<Entry>
HttpMethod method = HttpMethod.CACHE.get(value); HttpMethod method = HttpMethod.CACHE.get(value);
if (method != null) 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; break;
} }
@ -168,13 +168,13 @@ public class StaticTable implements Iterable<Entry>
HttpScheme scheme = HttpScheme.CACHE.get(value); HttpScheme scheme = HttpScheme.CACHE.get(value);
if (scheme != null) 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; break;
} }
case C_STATUS: 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; break;
} }
@ -184,7 +184,7 @@ public class StaticTable implements Iterable<Entry>
} }
if (entry == null) 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; _staticTable[i] = entry;
@ -201,7 +201,7 @@ public class StaticTable implements Iterable<Entry>
for (HttpHeader h : HttpHeader.values()) for (HttpHeader h : HttpHeader.values())
{ {
StaticEntry entry = _staticNameMap.get(h.asString()); Entry.StaticEntry entry = _staticNameMap.get(h.asString());
if (entry != null) if (entry != null)
_staticTableByHeader[h.ordinal()] = entry; _staticTableByHeader[h.ordinal()] = entry;
} }

View File

@ -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.HostPortHttpField;
import org.eclipse.jetty.http.HttpHeader; 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 public class AuthorityHttpField extends HostPortHttpField
{ {

View File

@ -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.HostPortHttpField;
import org.eclipse.jetty.http.HttpField; 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.HttpScheme;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http3.qpack.QpackException;
import org.eclipse.jetty.http3.qpack.QpackException.SessionException; import org.eclipse.jetty.http3.qpack.QpackException.SessionException;
public class MetaDataBuilder public class MetaDataBuilder

View File

@ -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.HttpField;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;

View File

@ -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;
}
}

View File

@ -11,13 +11,11 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack; package org.eclipse.jetty.http3.qpack.internal.util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.util.Utf8StringBuilder; public class HuffmanEncoder
public class Huffman
{ {
// Appendix C: Huffman Codes // 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) public static int octetsNeeded(String s)
{ {
return octetsNeeded(CODES, s); return octetsNeeded(CODES, s);

View File

@ -11,11 +11,11 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack; package org.eclipse.jetty.http3.qpack.internal.util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
public class NBitInteger public class NBitIntegerEncoder
{ {
public static int octectsNeeded(int n, int i) 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;
}
} }

View File

@ -11,7 +11,7 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.parser; package org.eclipse.jetty.http3.qpack.internal.util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;

View File

@ -11,11 +11,10 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.http3.qpack.parser; package org.eclipse.jetty.http3.qpack.internal.util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http3.qpack.HuffmanDecoder;
import org.eclipse.jetty.http3.qpack.QpackException; import org.eclipse.jetty.http3.qpack.QpackException;
public class NBitStringParser public class NBitStringParser
@ -69,10 +68,11 @@ public class NBitStringParser
if (_length < 0) if (_length < 0)
return null; return null;
_state = State.VALUE; _state = State.VALUE;
_huffmanBuilder.setLength(_length);
continue; continue;
case VALUE: case VALUE:
String value = _huffman ? _huffmanBuilder.decode(buffer, _length) : asciiStringDecode(buffer); String value = _huffman ? _huffmanBuilder.decode(buffer) : asciiStringDecode(buffer);
if (value != null) if (value != null)
reset(); reset();
return value; return value;

View File

@ -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;
}
}

View File

@ -17,7 +17,7 @@ import java.nio.ByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; 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.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;

View File

@ -17,14 +17,13 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http3.qpack.generator.IndexedNameEntryInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.IndexedNameEntryInstruction;
import org.eclipse.jetty.http3.qpack.generator.InsertCountIncrementInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.InsertCountIncrementInstruction;
import org.eclipse.jetty.http3.qpack.generator.Instruction; import org.eclipse.jetty.http3.qpack.internal.instruction.LiteralNameEntryInstruction;
import org.eclipse.jetty.http3.qpack.generator.LiteralNameEntryInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.SectionAcknowledgmentInstruction;
import org.eclipse.jetty.http3.qpack.generator.SectionAcknowledgmentInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.SetCapacityInstruction;
import org.eclipse.jetty.http3.qpack.generator.SetCapacityInstruction; import org.eclipse.jetty.http3.qpack.internal.parser.DecoderInstructionParser;
import org.eclipse.jetty.http3.qpack.parser.DecoderInstructionParser; import org.eclipse.jetty.http3.qpack.internal.parser.EncoderInstructionParser;
import org.eclipse.jetty.http3.qpack.parser.EncoderInstructionParser;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -17,7 +17,7 @@ import java.nio.ByteBuffer;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; 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.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;

View File

@ -18,6 +18,8 @@ import java.nio.ByteBuffer;
import java.util.Locale; import java.util.Locale;
import java.util.stream.Stream; 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.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
@ -51,7 +53,9 @@ public class HuffmanTest
public void testDecode(String specSection, String hex, String expected) throws Exception public void testDecode(String specSection, String hex, String expected) throws Exception
{ {
byte[] encoded = TypeUtil.fromHexString(hex); 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); assertEquals(expected, decoded, specSection);
} }
@ -61,11 +65,11 @@ public class HuffmanTest
{ {
ByteBuffer buf = BufferUtil.allocate(1024); ByteBuffer buf = BufferUtil.allocate(1024);
int pos = BufferUtil.flipToFill(buf); int pos = BufferUtil.flipToFill(buf);
Huffman.encode(buf, expected); HuffmanEncoder.encode(buf, expected);
BufferUtil.flipToFlush(buf, pos); BufferUtil.flipToFlush(buf, pos);
String encoded = TypeUtil.toHexString(BufferUtil.toArray(buf)).toLowerCase(Locale.ENGLISH); String encoded = TypeUtil.toHexString(BufferUtil.toArray(buf)).toLowerCase(Locale.ENGLISH);
assertEquals(hex, encoded, specSection); 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 @ParameterizedTest(name = "[{index}]") // don't include unprintable character in test display-name
@ -74,9 +78,9 @@ public class HuffmanTest
{ {
String s = "bad '" + bad + "'"; String s = "bad '" + bad + "'";
assertThat(Huffman.octetsNeeded(s), Matchers.is(-1)); assertThat(HuffmanEncoder.octetsNeeded(s), Matchers.is(-1));
assertThrows(BufferOverflowException.class, assertThrows(BufferOverflowException.class,
() -> Huffman.encode(BufferUtil.allocate(32), s)); () -> HuffmanEncoder.encode(BufferUtil.allocate(32), s));
} }
} }

View File

@ -13,9 +13,8 @@
package org.eclipse.jetty.http3.qpack; package org.eclipse.jetty.http3.qpack;
import org.eclipse.jetty.http3.qpack.generator.IndexedNameEntryInstruction; import org.eclipse.jetty.http3.qpack.internal.instruction.IndexedNameEntryInstruction;
import org.eclipse.jetty.http3.qpack.generator.Instruction; import org.eclipse.jetty.http3.qpack.internal.instruction.SectionAcknowledgmentInstruction;
import org.eclipse.jetty.http3.qpack.generator.SectionAcknowledgmentInstruction;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;

View File

@ -15,7 +15,7 @@ package org.eclipse.jetty.http3.qpack;
import java.nio.ByteBuffer; 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.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -15,6 +15,8 @@ package org.eclipse.jetty.http3.qpack;
import java.nio.ByteBuffer; 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.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -24,21 +26,22 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@SuppressWarnings("PointlessArithmeticExpression") @SuppressWarnings("PointlessArithmeticExpression")
public class NBitIntegerTest public class NBitIntegerTest
{ {
private final NBitIntegerParser _parser = new NBitIntegerParser();
@Test @Test
public void testOctetsNeeded() public void testOctetsNeeded()
{ {
assertEquals(0, NBitInteger.octectsNeeded(5, 10)); assertEquals(0, NBitIntegerEncoder.octectsNeeded(5, 10));
assertEquals(2, NBitInteger.octectsNeeded(5, 1337)); assertEquals(2, NBitIntegerEncoder.octectsNeeded(5, 1337));
assertEquals(1, NBitInteger.octectsNeeded(8, 42)); assertEquals(1, NBitIntegerEncoder.octectsNeeded(8, 42));
assertEquals(3, NBitInteger.octectsNeeded(8, 1337)); assertEquals(3, NBitIntegerEncoder.octectsNeeded(8, 1337));
assertEquals(0, NBitInteger.octectsNeeded(6, 62)); assertEquals(0, NBitIntegerEncoder.octectsNeeded(6, 62));
assertEquals(1, NBitInteger.octectsNeeded(6, 63)); assertEquals(1, NBitIntegerEncoder.octectsNeeded(6, 63));
assertEquals(1, NBitInteger.octectsNeeded(6, 64)); assertEquals(1, NBitIntegerEncoder.octectsNeeded(6, 64));
assertEquals(2, NBitInteger.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x01)); assertEquals(2, NBitIntegerEncoder.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x01));
assertEquals(3, NBitInteger.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80)); assertEquals(3, NBitIntegerEncoder.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80));
assertEquals(4, NBitInteger.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80 * 0x80)); assertEquals(4, NBitIntegerEncoder.octectsNeeded(6, 63 + 0x00 + 0x80 * 0x80 * 0x80));
} }
@Test @Test
@ -79,12 +82,12 @@ public class NBitIntegerTest
int p = BufferUtil.flipToFill(buf); int p = BufferUtil.flipToFill(buf);
if (n < 8) if (n < 8)
buf.put((byte)0x00); buf.put((byte)0x00);
NBitInteger.encode(buf, n, i); NBitIntegerEncoder.encode(buf, n, i);
BufferUtil.flipToFlush(buf, p); BufferUtil.flipToFlush(buf, p);
String r = TypeUtil.toHexString(BufferUtil.toArray(buf)); String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
assertEquals(expected, r); 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 @Test
@ -122,8 +125,8 @@ public class NBitIntegerTest
public void testDecode(int n, int expected, String encoded) public void testDecode(int n, int expected, String encoded)
{ {
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString(encoded)); ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
buf.position(n == 8 ? 0 : 1); _parser.setPrefix(n);
assertEquals(expected, NBitInteger.decode(buf, n)); assertEquals(expected, _parser.decode(buf));
} }
@Test @Test
@ -133,7 +136,7 @@ public class NBitIntegerTest
int p = BufferUtil.flipToFill(buf); int p = BufferUtil.flipToFill(buf);
buf.put((byte)0x77); buf.put((byte)0x77);
buf.put((byte)0xFF); buf.put((byte)0xFF);
NBitInteger.encode(buf, 5, 10); NBitIntegerEncoder.encode(buf, 5, 10);
BufferUtil.flipToFlush(buf, p); BufferUtil.flipToFlush(buf, p);
String r = TypeUtil.toHexString(BufferUtil.toArray(buf)); String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
@ -145,9 +148,9 @@ public class NBitIntegerTest
public void testDecodeExampleD11() public void testDecodeExampleD11()
{ {
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("77EaFF")); ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("77EaFF"));
buf.position(2); buf.position(1);
_parser.setPrefix(5);
assertEquals(10, NBitInteger.decode(buf, 5)); assertEquals(10, _parser.decode(buf));
} }
@Test @Test
@ -157,7 +160,7 @@ public class NBitIntegerTest
int p = BufferUtil.flipToFill(buf); int p = BufferUtil.flipToFill(buf);
buf.put((byte)0x88); buf.put((byte)0x88);
buf.put((byte)0x00); buf.put((byte)0x00);
NBitInteger.encode(buf, 5, 1337); NBitIntegerEncoder.encode(buf, 5, 1337);
BufferUtil.flipToFlush(buf, p); BufferUtil.flipToFlush(buf, p);
String r = TypeUtil.toHexString(BufferUtil.toArray(buf)); String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
@ -169,9 +172,9 @@ public class NBitIntegerTest
public void testDecodeExampleD12() public void testDecodeExampleD12()
{ {
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("881f9a0aff")); ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("881f9a0aff"));
buf.position(2); buf.position(1);
_parser.setPrefix(5);
assertEquals(1337, NBitInteger.decode(buf, 5)); assertEquals(1337, _parser.decode(buf));
} }
@Test @Test
@ -181,7 +184,7 @@ public class NBitIntegerTest
int p = BufferUtil.flipToFill(buf); int p = BufferUtil.flipToFill(buf);
buf.put((byte)0x88); buf.put((byte)0x88);
buf.put((byte)0xFF); buf.put((byte)0xFF);
NBitInteger.encode(buf, 8, 42); NBitIntegerEncoder.encode(buf, 8, 42);
BufferUtil.flipToFlush(buf, p); BufferUtil.flipToFlush(buf, p);
String r = TypeUtil.toHexString(BufferUtil.toArray(buf)); String r = TypeUtil.toHexString(BufferUtil.toArray(buf));
@ -194,7 +197,7 @@ public class NBitIntegerTest
{ {
ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("882aFf")); ByteBuffer buf = ByteBuffer.wrap(TypeUtil.fromHexString("882aFf"));
buf.position(1); buf.position(1);
_parser.setPrefix(8);
assertEquals(42, NBitInteger.decode(buf, 8)); assertEquals(42, _parser.decode(buf));
} }
} }

View File

@ -15,7 +15,6 @@ package org.eclipse.jetty.http3.qpack;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http3.qpack.generator.Instruction;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.NullByteBufferPool; import org.eclipse.jetty.io.NullByteBufferPool;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;

View File

@ -17,7 +17,6 @@ import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http3.qpack.generator.Instruction;
public class TestDecoderHandler implements QpackDecoder.Handler public class TestDecoderHandler implements QpackDecoder.Handler
{ {

View File

@ -16,8 +16,6 @@ package org.eclipse.jetty.http3.qpack;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
import org.eclipse.jetty.http3.qpack.generator.Instruction;
public class TestEncoderHandler implements QpackEncoder.Handler public class TestEncoderHandler implements QpackEncoder.Handler
{ {
private final Queue<Instruction> _instructionList = new LinkedList<>(); private final Queue<Instruction> _instructionList = new LinkedList<>();