Improve exceptions from QPACK
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
3d8433b58c
commit
63e4f1a074
|
@ -28,12 +28,16 @@ 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.EncodingException;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.eclipse.jetty.http3.qpack.QpackException.QPACK_DECODER_STREAM_ERROR;
|
||||
import static org.eclipse.jetty.http3.qpack.QpackException.QPACK_DECOMPRESSION_FAILED;
|
||||
|
||||
/**
|
||||
* Qpack Decoder
|
||||
* <p>This is not thread safe and may only be called by 1 thread at a time.</p>
|
||||
|
@ -98,18 +102,18 @@ public class QpackDecoder implements Dumpable
|
|||
|
||||
// If the buffer is big, don't even think about decoding it
|
||||
if (buffer.remaining() > _maxHeaderSize)
|
||||
throw new QpackException.SessionException("431 Request Header Fields too large");
|
||||
throw new QpackException.SessionException(QPACK_DECOMPRESSION_FAILED, "header_too_large");
|
||||
|
||||
_integerDecoder.setPrefix(8);
|
||||
int encodedInsertCount = _integerDecoder.decodeInt(buffer);
|
||||
if (encodedInsertCount < 0)
|
||||
throw new QpackException.CompressionException("Could not parse Required Insert Count");
|
||||
throw new QpackException.SessionException(QPACK_DECOMPRESSION_FAILED, "invalid_required_insert_count");
|
||||
|
||||
_integerDecoder.setPrefix(7);
|
||||
boolean signBit = (buffer.get(buffer.position()) & 0x80) != 0;
|
||||
int deltaBase = _integerDecoder.decodeInt(buffer);
|
||||
if (deltaBase < 0)
|
||||
throw new QpackException.CompressionException("Could not parse Delta Base");
|
||||
throw new QpackException.SessionException(QPACK_DECOMPRESSION_FAILED, "invalid_delta_base");
|
||||
|
||||
// Decode the Required Insert Count using the DynamicTable state.
|
||||
DynamicTable dynamicTable = _context.getDynamicTable();
|
||||
|
@ -117,24 +121,33 @@ public class QpackDecoder implements Dumpable
|
|||
int maxDynamicTableSize = dynamicTable.getCapacity();
|
||||
int requiredInsertCount = decodeInsertCount(encodedInsertCount, insertCount, maxDynamicTableSize);
|
||||
|
||||
// Parse the buffer into an Encoded Field Section.
|
||||
int base = signBit ? requiredInsertCount - deltaBase - 1 : requiredInsertCount + deltaBase;
|
||||
EncodedFieldSection encodedFieldSection = new EncodedFieldSection(streamId, handler, requiredInsertCount, base, buffer);
|
||||
try
|
||||
{
|
||||
// Parse the buffer into an Encoded Field Section.
|
||||
int base = signBit ? requiredInsertCount - deltaBase - 1 : requiredInsertCount + deltaBase;
|
||||
EncodedFieldSection encodedFieldSection = new EncodedFieldSection(streamId, handler, requiredInsertCount, base, buffer);
|
||||
|
||||
// Decode it straight away if we can, otherwise add it to the list of EncodedFieldSections.
|
||||
if (requiredInsertCount <= insertCount)
|
||||
{
|
||||
MetaData metaData = encodedFieldSection.decode(_context, _maxHeaderSize);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Decoded: streamId={}, metadata={}", streamId, metaData);
|
||||
_metaDataNotifications.add(new MetaDataNotification(streamId, metaData, handler));
|
||||
_instructions.add(new SectionAcknowledgmentInstruction(streamId));
|
||||
// Decode it straight away if we can, otherwise add it to the list of EncodedFieldSections.
|
||||
if (requiredInsertCount <= insertCount)
|
||||
{
|
||||
MetaData metaData = encodedFieldSection.decode(_context, _maxHeaderSize);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Decoded: streamId={}, metadata={}", streamId, metaData);
|
||||
_metaDataNotifications.add(new MetaDataNotification(streamId, metaData, handler));
|
||||
_instructions.add(new SectionAcknowledgmentInstruction(streamId));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Deferred Decoding: streamId={}, encodedFieldSection={}", streamId, encodedFieldSection);
|
||||
_encodedFieldSections.add(encodedFieldSection);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Throwable t)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Deferred Decoding: streamId={}, encodedFieldSection={}", streamId, encodedFieldSection);
|
||||
_encodedFieldSections.add(encodedFieldSection);
|
||||
notifyInstructionHandler();
|
||||
notifyMetaDataHandler();
|
||||
throw t;
|
||||
}
|
||||
|
||||
boolean hadMetaData = !_metaDataNotifications.isEmpty();
|
||||
|
@ -145,13 +158,23 @@ public class QpackDecoder implements Dumpable
|
|||
|
||||
public void parseInstructionBuffer(ByteBuffer buffer) throws QpackException
|
||||
{
|
||||
while (BufferUtil.hasContent(buffer))
|
||||
try
|
||||
{
|
||||
_parser.parse(buffer);
|
||||
while (BufferUtil.hasContent(buffer))
|
||||
{
|
||||
_parser.parse(buffer);
|
||||
}
|
||||
}
|
||||
catch (EncodingException e)
|
||||
{
|
||||
// There was an error decoding the instruction.
|
||||
throw new QpackException.SessionException(QPACK_DECODER_STREAM_ERROR, e.getMessage(), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
notifyInstructionHandler();
|
||||
notifyMetaDataHandler();
|
||||
}
|
||||
|
||||
notifyInstructionHandler();
|
||||
notifyMetaDataHandler();
|
||||
}
|
||||
|
||||
private void checkEncodedFieldSections() throws QpackException
|
||||
|
@ -230,7 +253,7 @@ public class QpackDecoder implements Dumpable
|
|||
int maxEntries = maxTableCapacity / 32;
|
||||
int fullRange = 2 * maxEntries;
|
||||
if (encInsertCount > fullRange)
|
||||
throw new QpackException.CompressionException("encInsertCount > fullRange");
|
||||
throw new QpackException.SessionException(QPACK_DECOMPRESSION_FAILED, "encInsertCount_greater_than_fullRange");
|
||||
|
||||
// MaxWrapped is the largest possible value of ReqInsertCount that is 0 mod 2 * MaxEntries.
|
||||
int maxValue = totalNumInserts + maxEntries;
|
||||
|
@ -241,13 +264,13 @@ public class QpackDecoder implements Dumpable
|
|||
if (reqInsertCount > maxValue)
|
||||
{
|
||||
if (reqInsertCount <= fullRange)
|
||||
throw new QpackException.CompressionException("reqInsertCount <= fullRange");
|
||||
throw new QpackException.SessionException(QPACK_DECOMPRESSION_FAILED, "reqInsertCount_less_than_or_equal_to_fullRange");
|
||||
reqInsertCount -= fullRange;
|
||||
}
|
||||
|
||||
// Value of 0 must be encoded as 0.
|
||||
if (reqInsertCount == 0)
|
||||
throw new QpackException.CompressionException("reqInsertCount == 0");
|
||||
throw new QpackException.SessionException(QPACK_DECOMPRESSION_FAILED, "reqInsertCount_is_zero");
|
||||
|
||||
return reqInsertCount;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@ import org.eclipse.jetty.util.component.Dumpable;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.eclipse.jetty.http3.qpack.QpackException.H3_GENERAL_PROTOCOL_ERROR;
|
||||
import static org.eclipse.jetty.http3.qpack.QpackException.QPACK_ENCODER_STREAM_ERROR;
|
||||
|
||||
public class QpackEncoder implements Dumpable
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(QpackEncoder.class);
|
||||
|
@ -180,7 +183,7 @@ public class QpackEncoder implements Dumpable
|
|||
String name = field.getName();
|
||||
char firstChar = name.charAt(0);
|
||||
if (firstChar <= ' ')
|
||||
throw new QpackException.StreamException("Invalid header name: '%s'", name);
|
||||
throw new QpackException.StreamException(H3_GENERAL_PROTOCOL_ERROR, String.format("Invalid header name: '%s'", name));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +316,7 @@ public class QpackEncoder implements Dumpable
|
|||
|
||||
int insertCount = _context.getDynamicTable().getInsertCount();
|
||||
if (_knownInsertCount + increment > insertCount)
|
||||
throw new QpackException.StreamException("KnownInsertCount incremented over InsertCount");
|
||||
throw new QpackException.SessionException(QPACK_ENCODER_STREAM_ERROR, "KnownInsertCount incremented over InsertCount");
|
||||
_knownInsertCount += increment;
|
||||
}
|
||||
|
||||
|
@ -324,7 +327,7 @@ public class QpackEncoder implements Dumpable
|
|||
|
||||
StreamInfo streamInfo = _streamInfoMap.get(streamId);
|
||||
if (streamInfo == null)
|
||||
throw new QpackException.StreamException("No StreamInfo for " + streamId);
|
||||
throw new QpackException.SessionException(QPACK_ENCODER_STREAM_ERROR, "No StreamInfo for " + streamId);
|
||||
|
||||
// The KnownInsertCount should be updated to the earliest sent RequiredInsertCount on that stream.
|
||||
StreamInfo.SectionInfo sectionInfo = streamInfo.acknowledge();
|
||||
|
@ -343,7 +346,7 @@ public class QpackEncoder implements Dumpable
|
|||
|
||||
StreamInfo streamInfo = _streamInfoMap.remove(streamId);
|
||||
if (streamInfo == null)
|
||||
throw new QpackException.StreamException("No StreamInfo for " + streamId);
|
||||
throw new QpackException.SessionException(QPACK_ENCODER_STREAM_ERROR, "No StreamInfo for " + streamId);
|
||||
|
||||
// Release all referenced entries outstanding on the stream that was cancelled.
|
||||
for (StreamInfo.SectionInfo sectionInfo : streamInfo)
|
||||
|
|
|
@ -16,9 +16,22 @@ package org.eclipse.jetty.http3.qpack;
|
|||
@SuppressWarnings("serial")
|
||||
public abstract class QpackException extends Exception
|
||||
{
|
||||
QpackException(String messageFormat, Object... args)
|
||||
public static final int QPACK_DECOMPRESSION_FAILED = 0x200;
|
||||
public static final int QPACK_ENCODER_STREAM_ERROR = 0x201;
|
||||
public static final int QPACK_DECODER_STREAM_ERROR = 0x202;
|
||||
public static final int H3_GENERAL_PROTOCOL_ERROR = 0x0101;
|
||||
|
||||
private final int _errorCode;
|
||||
|
||||
QpackException(int errorCode, String messageFormat, Throwable cause)
|
||||
{
|
||||
super(String.format(messageFormat, args));
|
||||
super(messageFormat, cause);
|
||||
_errorCode = errorCode;
|
||||
}
|
||||
|
||||
public int getErrorCode()
|
||||
{
|
||||
return _errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,9 +43,14 @@ public abstract class QpackException extends Exception
|
|||
*/
|
||||
public static class StreamException extends QpackException
|
||||
{
|
||||
public StreamException(String messageFormat, Object... args)
|
||||
public StreamException(int errorCode, String messageFormat)
|
||||
{
|
||||
super(messageFormat, args);
|
||||
this(errorCode, messageFormat, null);
|
||||
}
|
||||
|
||||
public StreamException(int errorCode, String messageFormat, Throwable cause)
|
||||
{
|
||||
super(errorCode, messageFormat, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,17 +61,14 @@ public abstract class QpackException extends Exception
|
|||
*/
|
||||
public static class SessionException extends QpackException
|
||||
{
|
||||
public SessionException(String messageFormat, Object... args)
|
||||
public SessionException(int errorCode, String message)
|
||||
{
|
||||
super(messageFormat, args);
|
||||
this(errorCode, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CompressionException extends SessionException
|
||||
{
|
||||
public CompressionException(String messageFormat, Object... args)
|
||||
public SessionException(int errorCode, String message, Throwable cause)
|
||||
{
|
||||
super(messageFormat, args);
|
||||
super(errorCode, message, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import org.eclipse.jetty.http.HttpVersion;
|
|||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
|
||||
import static org.eclipse.jetty.http3.qpack.QpackException.H3_GENERAL_PROTOCOL_ERROR;
|
||||
|
||||
public class MetaDataBuilder
|
||||
{
|
||||
private final int _maxSize;
|
||||
|
@ -72,12 +74,12 @@ public class MetaDataBuilder
|
|||
HttpHeader header = field.getHeader();
|
||||
String name = field.getName();
|
||||
if (name == null || name.length() == 0)
|
||||
throw new QpackException.SessionException("Header size 0");
|
||||
throw new QpackException.SessionException(QpackException.QPACK_DECOMPRESSION_FAILED, "Header size 0");
|
||||
String value = field.getValue();
|
||||
int fieldSize = name.length() + (value == null ? 0 : value.length());
|
||||
_size += fieldSize + 32;
|
||||
if (_size > _maxSize)
|
||||
throw new QpackException.SessionException("Header size %d > %d", _size, _maxSize);
|
||||
throw new QpackException.SessionException(QpackException.QPACK_DECOMPRESSION_FAILED, String.format("Header size %d > %d", _size, _maxSize));
|
||||
|
||||
if (field instanceof StaticTableHttpField)
|
||||
{
|
||||
|
@ -198,7 +200,7 @@ public class MetaDataBuilder
|
|||
|
||||
protected void streamException(String messageFormat, Object... args)
|
||||
{
|
||||
QpackException.StreamException stream = new QpackException.StreamException(messageFormat, args);
|
||||
QpackException.StreamException stream = new QpackException.StreamException(QpackException.QPACK_DECOMPRESSION_FAILED, String.format(messageFormat, args));
|
||||
if (_streamException == null)
|
||||
_streamException = stream;
|
||||
else
|
||||
|
@ -227,7 +229,7 @@ public class MetaDataBuilder
|
|||
}
|
||||
|
||||
if (_request && _response)
|
||||
throw new QpackException.StreamException("Request and Response headers");
|
||||
throw new QpackException.StreamException(H3_GENERAL_PROTOCOL_ERROR, "Request and Response headers");
|
||||
|
||||
HttpFields.Mutable fields = _fields;
|
||||
try
|
||||
|
@ -235,14 +237,14 @@ public class MetaDataBuilder
|
|||
if (_request)
|
||||
{
|
||||
if (_method == null)
|
||||
throw new QpackException.StreamException("No Method");
|
||||
throw new QpackException.StreamException(H3_GENERAL_PROTOCOL_ERROR, "No Method");
|
||||
boolean isConnect = HttpMethod.CONNECT.is(_method);
|
||||
if (!isConnect || _protocol != null)
|
||||
{
|
||||
if (_scheme == null)
|
||||
throw new QpackException.StreamException("No Scheme");
|
||||
throw new QpackException.StreamException(H3_GENERAL_PROTOCOL_ERROR, "No Scheme");
|
||||
if (_path == null)
|
||||
throw new QpackException.StreamException("No Path");
|
||||
throw new QpackException.StreamException(H3_GENERAL_PROTOCOL_ERROR, "No Path");
|
||||
}
|
||||
if (isConnect)
|
||||
return new MetaData.ConnectRequest(_scheme, _authority, _path, fields, _protocol);
|
||||
|
@ -259,7 +261,7 @@ public class MetaDataBuilder
|
|||
if (_response)
|
||||
{
|
||||
if (_status == null)
|
||||
throw new QpackException.StreamException("No Status");
|
||||
throw new QpackException.StreamException(H3_GENERAL_PROTOCOL_ERROR, "No Status");
|
||||
return new MetaData.Response(HttpVersion.HTTP_3, _status, fields, _contentLength);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ 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.EncodingException;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitStringParser;
|
||||
|
||||
|
@ -69,7 +70,7 @@ public class DecoderInstructionParser
|
|||
_integerParser = new NBitIntegerParser();
|
||||
}
|
||||
|
||||
public void parse(ByteBuffer buffer) throws QpackException
|
||||
public void parse(ByteBuffer buffer) throws QpackException, EncodingException
|
||||
{
|
||||
if (buffer == null || !buffer.hasRemaining())
|
||||
return;
|
||||
|
@ -123,7 +124,7 @@ public class DecoderInstructionParser
|
|||
}
|
||||
}
|
||||
|
||||
private void parseInsertNameWithReference(ByteBuffer buffer) throws QpackException
|
||||
private void parseInsertNameWithReference(ByteBuffer buffer) throws QpackException, EncodingException
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
@ -162,7 +163,7 @@ public class DecoderInstructionParser
|
|||
}
|
||||
}
|
||||
|
||||
private void parseInsertWithLiteralName(ByteBuffer buffer) throws QpackException
|
||||
private void parseInsertWithLiteralName(ByteBuffer buffer) throws QpackException, EncodingException
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
|
|
@ -23,12 +23,15 @@ import org.eclipse.jetty.http3.qpack.QpackDecoder;
|
|||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.http3.qpack.internal.QpackContext;
|
||||
import org.eclipse.jetty.http3.qpack.internal.metadata.MetaDataBuilder;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.EncodingException;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerParser;
|
||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitStringParser;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.eclipse.jetty.http3.qpack.QpackException.QPACK_DECOMPRESSION_FAILED;
|
||||
|
||||
public class EncodedFieldSection
|
||||
{
|
||||
public static final Logger LOG = LoggerFactory.getLogger(EncodedFieldSection.class);
|
||||
|
@ -49,22 +52,29 @@ public class EncodedFieldSection
|
|||
_base = base;
|
||||
_handler = handler;
|
||||
|
||||
while (content.hasRemaining())
|
||||
try
|
||||
{
|
||||
EncodedField encodedField;
|
||||
byte firstByte = content.get(content.position());
|
||||
if ((firstByte & 0x80) != 0)
|
||||
encodedField = parseIndexedField(content);
|
||||
else if ((firstByte & 0x40) != 0)
|
||||
encodedField = parseNameReference(content);
|
||||
else if ((firstByte & 0x20) != 0)
|
||||
encodedField = parseLiteralField(content);
|
||||
else if ((firstByte & 0x10) != 0)
|
||||
encodedField = parseIndexedFieldPostBase(content);
|
||||
else
|
||||
encodedField = parseNameReferencePostBase(content);
|
||||
while (content.hasRemaining())
|
||||
{
|
||||
EncodedField encodedField;
|
||||
byte firstByte = content.get(content.position());
|
||||
if ((firstByte & 0x80) != 0)
|
||||
encodedField = parseIndexedField(content);
|
||||
else if ((firstByte & 0x40) != 0)
|
||||
encodedField = parseNameReference(content);
|
||||
else if ((firstByte & 0x20) != 0)
|
||||
encodedField = parseLiteralField(content);
|
||||
else if ((firstByte & 0x10) != 0)
|
||||
encodedField = parseIndexedFieldPostBase(content);
|
||||
else
|
||||
encodedField = parseNameReferencePostBase(content);
|
||||
|
||||
_encodedFields.add(encodedField);
|
||||
_encodedFields.add(encodedField);
|
||||
}
|
||||
}
|
||||
catch (EncodingException e)
|
||||
{
|
||||
throw new QpackException.SessionException(QPACK_DECOMPRESSION_FAILED, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,28 +107,28 @@ public class EncodedFieldSection
|
|||
return metaDataBuilder.build();
|
||||
}
|
||||
|
||||
private EncodedField parseIndexedField(ByteBuffer buffer) throws QpackException
|
||||
private EncodedField parseIndexedField(ByteBuffer buffer) throws EncodingException
|
||||
{
|
||||
byte firstByte = buffer.get(buffer.position());
|
||||
boolean dynamicTable = (firstByte & 0x40) == 0;
|
||||
_integerParser.setPrefix(6);
|
||||
int index = _integerParser.decodeInt(buffer);
|
||||
if (index < 0)
|
||||
throw new QpackException.CompressionException("Invalid Index");
|
||||
throw new EncodingException("invalid_index");
|
||||
return new IndexedField(dynamicTable, index);
|
||||
}
|
||||
|
||||
private EncodedField parseIndexedFieldPostBase(ByteBuffer buffer) throws QpackException
|
||||
private EncodedField parseIndexedFieldPostBase(ByteBuffer buffer) throws EncodingException
|
||||
{
|
||||
_integerParser.setPrefix(4);
|
||||
int index = _integerParser.decodeInt(buffer);
|
||||
if (index < 0)
|
||||
throw new QpackException.CompressionException("Invalid Index");
|
||||
throw new EncodingException("Invalid Index");
|
||||
|
||||
return new PostBaseIndexedField(index);
|
||||
}
|
||||
|
||||
private EncodedField parseNameReference(ByteBuffer buffer) throws QpackException
|
||||
private EncodedField parseNameReference(ByteBuffer buffer) throws EncodingException
|
||||
{
|
||||
LOG.info("parseLiteralFieldLineWithNameReference: " + BufferUtil.toDetailString(buffer));
|
||||
|
||||
|
@ -129,17 +139,17 @@ public class EncodedFieldSection
|
|||
_integerParser.setPrefix(4);
|
||||
int nameIndex = _integerParser.decodeInt(buffer);
|
||||
if (nameIndex < 0)
|
||||
throw new QpackException.CompressionException("Invalid Name Index");
|
||||
throw new EncodingException("invalid_name_index");
|
||||
|
||||
_stringParser.setPrefix(8);
|
||||
String value = _stringParser.decode(buffer);
|
||||
if (value == null)
|
||||
throw new QpackException.CompressionException("Incomplete Value");
|
||||
throw new EncodingException("incomplete_value");
|
||||
|
||||
return new IndexedNameField(allowEncoding, dynamicTable, nameIndex, value);
|
||||
}
|
||||
|
||||
private EncodedField parseNameReferencePostBase(ByteBuffer buffer) throws QpackException
|
||||
private EncodedField parseNameReferencePostBase(ByteBuffer buffer) throws EncodingException
|
||||
{
|
||||
byte firstByte = buffer.get(buffer.position());
|
||||
boolean allowEncoding = (firstByte & 0x08) != 0;
|
||||
|
@ -147,17 +157,17 @@ public class EncodedFieldSection
|
|||
_integerParser.setPrefix(3);
|
||||
int nameIndex = _integerParser.decodeInt(buffer);
|
||||
if (nameIndex < 0)
|
||||
throw new QpackException.CompressionException("Invalid Index");
|
||||
throw new EncodingException("invalid_index");
|
||||
|
||||
_stringParser.setPrefix(8);
|
||||
String value = _stringParser.decode(buffer);
|
||||
if (value == null)
|
||||
throw new QpackException.CompressionException("Invalid Value");
|
||||
throw new EncodingException("invalid_value");
|
||||
|
||||
return new PostBaseIndexedNameField(allowEncoding, nameIndex, value);
|
||||
}
|
||||
|
||||
private EncodedField parseLiteralField(ByteBuffer buffer) throws QpackException
|
||||
private EncodedField parseLiteralField(ByteBuffer buffer) throws EncodingException
|
||||
{
|
||||
byte firstByte = buffer.get(buffer.position());
|
||||
boolean allowEncoding = (firstByte & 0x10) != 0;
|
||||
|
@ -165,12 +175,12 @@ public class EncodedFieldSection
|
|||
_stringParser.setPrefix(4);
|
||||
String name = _stringParser.decode(buffer);
|
||||
if (name == null)
|
||||
throw new QpackException.CompressionException("Invalid Name");
|
||||
throw new EncodingException("invalid_name");
|
||||
|
||||
_stringParser.setPrefix(8);
|
||||
String value = _stringParser.decode(buffer);
|
||||
if (value == null)
|
||||
throw new QpackException.CompressionException("Invalid Value");
|
||||
throw new EncodingException("invalid_value");
|
||||
|
||||
return new LiteralField(allowEncoding, name, value);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
|
||||
public class DynamicTable implements Iterable<Entry>, Dumpable
|
||||
|
@ -134,10 +133,10 @@ public class DynamicTable implements Iterable<Entry>, Dumpable
|
|||
* @param absoluteIndex the absolute index of the entry in the table.
|
||||
* @return the entry with the absolute index.
|
||||
*/
|
||||
public Entry getAbsolute(int absoluteIndex) throws QpackException
|
||||
public Entry getAbsolute(int absoluteIndex)
|
||||
{
|
||||
if (absoluteIndex < 0)
|
||||
throw new QpackException.CompressionException("Invalid Index");
|
||||
throw new IllegalArgumentException("Invalid Index");
|
||||
|
||||
if (_entries.isEmpty())
|
||||
throw new IllegalArgumentException("Invalid Index");
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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;
|
||||
|
||||
public class EncodingException extends Exception
|
||||
{
|
||||
public EncodingException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@ 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
|
||||
|
@ -39,7 +38,7 @@ public class HuffmanDecoder
|
|||
_length = length;
|
||||
}
|
||||
|
||||
public String decode(ByteBuffer buffer) throws QpackException.CompressionException
|
||||
public String decode(ByteBuffer buffer) throws EncodingException
|
||||
{
|
||||
for (; _count < _length; _count++)
|
||||
{
|
||||
|
@ -58,7 +57,7 @@ public class HuffmanDecoder
|
|||
if (rowsym[_node] == EOS)
|
||||
{
|
||||
reset();
|
||||
throw new QpackException.CompressionException("EOS in content");
|
||||
throw new EncodingException("eos_in_content");
|
||||
}
|
||||
|
||||
// terminal node
|
||||
|
@ -89,7 +88,7 @@ public class HuffmanDecoder
|
|||
}
|
||||
|
||||
if ((c >> (8 - _bits)) != requiredPadding)
|
||||
throw new QpackException.CompressionException("Incorrect padding");
|
||||
throw new EncodingException("incorrect_padding");
|
||||
|
||||
_node = lastNode;
|
||||
break;
|
||||
|
@ -103,7 +102,7 @@ public class HuffmanDecoder
|
|||
if (_node != 0)
|
||||
{
|
||||
reset();
|
||||
throw new QpackException.CompressionException("Bad termination");
|
||||
throw new EncodingException("bad_termination");
|
||||
}
|
||||
|
||||
String value = _utf8.toString();
|
||||
|
|
|
@ -15,8 +15,6 @@ package org.eclipse.jetty.http3.qpack.internal.util;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http3.qpack.QpackException;
|
||||
|
||||
public class NBitStringParser
|
||||
{
|
||||
private final NBitIntegerParser _integerParser;
|
||||
|
@ -50,7 +48,7 @@ public class NBitStringParser
|
|||
_prefix = prefix;
|
||||
}
|
||||
|
||||
public String decode(ByteBuffer buffer) throws QpackException
|
||||
public String decode(ByteBuffer buffer) throws EncodingException
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue