Use setPrefix API for NBitIntegerParser

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2021-02-13 01:54:10 +11:00 committed by Simone Bordet
parent 12a64b1637
commit 9d9e13cf3a
6 changed files with 68 additions and 28 deletions

View File

@ -19,6 +19,7 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpTokens; import org.eclipse.jetty.http.HttpTokens;
import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http3.qpack.generator.Instruction;
import org.eclipse.jetty.http3.qpack.table.Entry; import org.eclipse.jetty.http3.qpack.table.Entry;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -59,6 +60,13 @@ public class QpackDecoder
_localMaxDynamicTableSize = localMaxdynamciTableSize; _localMaxDynamicTableSize = localMaxdynamciTableSize;
} }
public interface Handler
{
void onMetadata(MetaData metaData);
void onInstruction(Instruction instruction);
}
public MetaData decode(ByteBuffer buffer) throws QpackException.SessionException, QpackException.StreamException public MetaData decode(ByteBuffer buffer) throws QpackException.SessionException, QpackException.StreamException
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())

View File

@ -26,11 +26,11 @@ public class DecoderInstructionParser
private final Handler _handler; private final Handler _handler;
private final NBitIntegerParser _integerParser; private final NBitIntegerParser _integerParser;
private State _state = State.PARSING; private State _state = State.IDLE;
private enum State private enum State
{ {
PARSING, IDLE,
SECTION_ACKNOWLEDGEMENT, SECTION_ACKNOWLEDGEMENT,
STREAM_CANCELLATION, STREAM_CANCELLATION,
INSERT_COUNT_INCREMENT INSERT_COUNT_INCREMENT
@ -58,22 +58,25 @@ public class DecoderInstructionParser
switch (_state) switch (_state)
{ {
case PARSING: case IDLE:
// Get first byte without incrementing the buffers position. // Get first byte without incrementing the buffers position.
byte firstByte = buffer.get(buffer.position()); byte firstByte = buffer.get(buffer.position());
if ((firstByte & 0x80) != 0) if ((firstByte & 0x80) != 0)
{ {
_state = State.SECTION_ACKNOWLEDGEMENT; _state = State.SECTION_ACKNOWLEDGEMENT;
_integerParser.setPrefix(SECTION_ACKNOWLEDGEMENT_PREFIX);
parseSectionAcknowledgment(buffer); parseSectionAcknowledgment(buffer);
} }
else if ((firstByte & 0x40) != 0) else if ((firstByte & 0x40) != 0)
{ {
_state = State.STREAM_CANCELLATION; _state = State.STREAM_CANCELLATION;
_integerParser.setPrefix(STREAM_CANCELLATION_PREFIX);
parseStreamCancellation(buffer); parseStreamCancellation(buffer);
} }
else else
{ {
_state = State.INSERT_COUNT_INCREMENT; _state = State.INSERT_COUNT_INCREMENT;
_integerParser.setPrefix(INSERT_COUNT_INCREMENT_PREFIX);
parseInsertCountIncrement(buffer); parseInsertCountIncrement(buffer);
} }
break; break;
@ -97,31 +100,37 @@ public class DecoderInstructionParser
private void parseSectionAcknowledgment(ByteBuffer buffer) private void parseSectionAcknowledgment(ByteBuffer buffer)
{ {
int streamId = _integerParser.decode(buffer, SECTION_ACKNOWLEDGEMENT_PREFIX); int streamId = _integerParser.decode(buffer);
if (streamId >= 0) if (streamId >= 0)
{ {
_state = State.PARSING; reset();
_handler.onSectionAcknowledgement(streamId); _handler.onSectionAcknowledgement(streamId);
} }
} }
private void parseStreamCancellation(ByteBuffer buffer) private void parseStreamCancellation(ByteBuffer buffer)
{ {
int streamId = _integerParser.decode(buffer, STREAM_CANCELLATION_PREFIX); int streamId = _integerParser.decode(buffer);
if (streamId >= 0) if (streamId >= 0)
{ {
_state = State.PARSING; reset();
_handler.onStreamCancellation(streamId); _handler.onStreamCancellation(streamId);
} }
} }
private void parseInsertCountIncrement(ByteBuffer buffer) private void parseInsertCountIncrement(ByteBuffer buffer)
{ {
int increment = _integerParser.decode(buffer, INSERT_COUNT_INCREMENT_PREFIX); int increment = _integerParser.decode(buffer);
if (increment >= 0) if (increment >= 0)
{ {
_state = State.PARSING; reset();
_handler.onInsertCountIncrement(increment); _handler.onInsertCountIncrement(increment);
} }
} }
public void reset()
{
_state = State.IDLE;
_integerParser.reset();
}
} }

View File

@ -89,11 +89,13 @@ public class EncoderInstructionParser
else if ((firstByte & 0x20) != 0) else if ((firstByte & 0x20) != 0)
{ {
_state = State.SET_CAPACITY; _state = State.SET_CAPACITY;
_integerParser.setPrefix(5);
parseSetDynamicTableCapacity(buffer); parseSetDynamicTableCapacity(buffer);
} }
else else
{ {
_state = State.DUPLICATE; _state = State.DUPLICATE;
_integerParser.setPrefix(5);
parseDuplicate(buffer); parseDuplicate(buffer);
} }
break; break;
@ -129,24 +131,27 @@ public class EncoderInstructionParser
byte firstByte = buffer.get(buffer.position()); byte firstByte = buffer.get(buffer.position());
_referenceDynamicTable = (firstByte & 0x40) == 0; _referenceDynamicTable = (firstByte & 0x40) == 0;
_operation = Operation.INDEX; _operation = Operation.INDEX;
_integerParser.setPrefix(6);
continue; continue;
case INDEX: case INDEX:
_index = _integerParser.decode(buffer, 6); _index = _integerParser.decode(buffer);
if (_index < 0) if (_index < 0)
return; return;
_stringParser.setPrefix(8);
_operation = Operation.VALUE; _operation = Operation.VALUE;
_stringParser.setPrefix(8);
continue; continue;
case VALUE: case VALUE:
String value = _stringParser.decode(buffer); String value = _stringParser.decode(buffer);
if (value == null) if (value == null)
return; return;
_operation = Operation.NONE;
_state = State.PARSING; int index = _index;
_handler.onInsertNameWithReference(_index, _referenceDynamicTable, value); boolean dynamic = _referenceDynamicTable;
reset();
_handler.onInsertNameWithReference(index, dynamic, value);
return; return;
default: default:
@ -162,8 +167,8 @@ public class EncoderInstructionParser
switch (_operation) switch (_operation)
{ {
case NONE: case NONE:
_stringParser.setPrefix(6);
_operation = Operation.NAME; _operation = Operation.NAME;
_stringParser.setPrefix(6);
continue; continue;
case NAME: case NAME:
@ -171,8 +176,8 @@ public class EncoderInstructionParser
if (_name == null) if (_name == null)
return; return;
_stringParser.setPrefix(8);
_operation = Operation.VALUE; _operation = Operation.VALUE;
_stringParser.setPrefix(8);
continue; continue;
case VALUE: case VALUE:
@ -180,9 +185,9 @@ public class EncoderInstructionParser
if (value == null) if (value == null)
return; return;
_operation = Operation.NONE; String name = _name;
_state = State.PARSING; reset();
_handler.onInsertWithLiteralName(_name, value); _handler.onInsertWithLiteralName(name, value);
return; return;
default: default:
@ -193,21 +198,32 @@ public class EncoderInstructionParser
private void parseDuplicate(ByteBuffer buffer) private void parseDuplicate(ByteBuffer buffer)
{ {
int index = _integerParser.decode(buffer, 5); int index = _integerParser.decode(buffer);
if (index >= 0) if (index >= 0)
{ {
_state = State.PARSING; reset();
_handler.onDuplicate(index); _handler.onDuplicate(index);
} }
} }
private void parseSetDynamicTableCapacity(ByteBuffer buffer) private void parseSetDynamicTableCapacity(ByteBuffer buffer)
{ {
int capacity = _integerParser.decode(buffer, 5); int capacity = _integerParser.decode(buffer);
if (capacity >= 0) if (capacity >= 0)
{ {
_state = State.PARSING; reset();
_handler.onSetDynamicTableCapacity(capacity); _handler.onSetDynamicTableCapacity(capacity);
} }
} }
public void reset()
{
_stringParser.reset();
_integerParser.reset();
_state = State.PARSING;
_operation = Operation.NONE;
_referenceDynamicTable = false;
_index = -1;
_name = null;
}
} }

View File

@ -22,7 +22,12 @@ public class NBitIntegerParser
private int _multiplier; private int _multiplier;
private boolean _started; private boolean _started;
public int decode(ByteBuffer buffer, int prefix) public void setPrefix(int prefix)
{
_prefix = prefix;
}
public int decode(ByteBuffer buffer)
{ {
if (!_started) if (!_started)
{ {
@ -30,7 +35,6 @@ public class NBitIntegerParser
return -1; return -1;
_started = true; _started = true;
_prefix = prefix;
_multiplier = 1; _multiplier = 1;
int nbits = 0xFF >>> (8 - _prefix); int nbits = 0xFF >>> (8 - _prefix);
_total = buffer.get() & nbits; _total = buffer.get() & nbits;

View File

@ -59,10 +59,11 @@ public class NBitStringParser
byte firstByte = buffer.get(buffer.position()); byte firstByte = buffer.get(buffer.position());
_huffman = ((0x80 >>> (8 - _prefix)) & firstByte) != 0; _huffman = ((0x80 >>> (8 - _prefix)) & firstByte) != 0;
_state = State.LENGTH; _state = State.LENGTH;
_integerParser.setPrefix(_prefix - 1);
continue; continue;
case LENGTH: case LENGTH:
_length = _integerParser.decode(buffer, _prefix - 1); _length = _integerParser.decode(buffer);
if (_length < 0) if (_length < 0)
return null; return null;
_state = State.VALUE; _state = State.VALUE;

View File

@ -37,10 +37,12 @@ public class NBitIntegerParserTest
ByteBuffer buffer1 = BufferUtil.toBuffer(bytes, 0, 2); ByteBuffer buffer1 = BufferUtil.toBuffer(bytes, 0, 2);
ByteBuffer buffer2 = BufferUtil.toBuffer(bytes, 2, 1); ByteBuffer buffer2 = BufferUtil.toBuffer(bytes, 2, 1);
int value = parser.decode(buffer1, 7); parser.setPrefix(7);
int value = parser.decode(buffer1);
assertThat(value, is(-1)); assertThat(value, is(-1));
value = parser.decode(buffer2, 7); parser.setPrefix(7);
value = parser.decode(buffer2);
assertThat(value, is(1337)); assertThat(value, is(1337));
} }
} }