if (LOG.isDebugEnabled())
LOG.debug(String.format("CtxTbl[%x] decoding %d octets",_context.hashCode(),buffer.remaining()));
// If the buffer is big, don't even think about decoding it
if (buffer.remaining()>_builder.getMaxSize())
throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header frame size "+buffer.remaining()+">"+_builder.getMaxSize());
while(buffer.hasRemaining())
{
if (LOG.isDebugEnabled())
{
int l=Math.min(buffer.remaining(),16);
LOG.debug("decode "+TypeUtil.toHexString(buffer.array(),buffer.arrayOffset()+buffer.position(),l)+(l<buffer.remaining()?"...":""));
}
byte b = buffer.get();
if (b<0)
{
// 7.1 indexed if the high bit is set
int index = NBitInteger.decode(buffer,7);
Entry entry=_context.get(index);
if (entry==null)
{
throw new BadMessageException("Unknown index "+index);
}
else if (entry.isStatic())
{
if (LOG.isDebugEnabled())
LOG.debug("decode IdxStatic {}",entry);
// emit field
_builder.emit(entry.getHttpField());
// TODO copy and add to reference set if there is room
// _context.add(entry.getHttpField());
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("decode Idx {}",entry);
// emit
_builder.emit(entry.getHttpField());
}
}
else
{
// look at the first nibble in detail
byte f= (byte)((b&0xF0)>>4);
String name;
HttpHeader header;
String value;
boolean indexed;
int name_index;
switch (f)
{
case 2: // 7.3
case 3: // 7.3
// change table size
int size = NBitInteger.decode(buffer,5);
if (LOG.isDebugEnabled())
LOG.debug("decode resize="+size);
if (size>_localMaxHeaderTableSize)
throw new IllegalArgumentException();
_context.resize(size);
continue;
case 0: // 7.2.2
case 1: // 7.2.3
indexed=false;
name_index=NBitInteger.decode(buffer,4);
break;
case 4: // 7.2.1
case 5: // 7.2.1
case 6: // 7.2.1
case 7: // 7.2.1
indexed=true;
name_index=NBitInteger.decode(buffer,6);
break;
default:
throw new IllegalStateException();
}
boolean huffmanName=false;
// decode the name
if (name_index>0)
{
Entry name_entry=_context.get(name_index);
name=name_entry.getHttpField().getName();
header=name_entry.getHttpField().getHeader();
}
else
{
huffmanName = (buffer.get()&0x80)==0x80;
int length = NBitInteger.decode(buffer,7);
_builder.checkSize(length,huffmanName);
if (huffmanName)
name=Huffman.decode(buffer,length);
else
name=toASCIIString(buffer,length);
for (int i=0;i<name.length();i++)
{
char c=name.charAt(i);
if (c>='A'&&c<='Z')
{
throw new BadMessageException(400,"Uppercase header name");
}
}
header=HttpHeader.CACHE.get(name);
}