package com.webpieces.hpack.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.webpieces.data.api.DataWrapper;
import com.twitter.hpack.Decoder;
import com.webpieces.http2parser.api.ConnectionException;
import com.webpieces.http2parser.api.Http2Exception;
import com.webpieces.http2parser.api.ParseFailReason;
import com.webpieces.http2parser.api.StreamException;
import com.webpieces.http2parser.api.dto.lib.Http2Header;
public class HeaderDecoding {
public void setMaxHeaderTableSize(Decoder decoder, int newSize) {
synchronized(decoder) {
decoder.setMaxHeaderTableSize(newSize);
}
}
public List<Http2Header> decode(Decoder decoder, DataWrapper data, int streamId) {
try {
return decodeImpl(decoder, data, streamId);
} catch (IOException e) {
// TODO: this doesn't catch the h2spec -s 4.3 invalid header block fragment
throw new ConnectionException(ParseFailReason.HEADER_DECODE, streamId, "Error from hpack library", e);
//TODO: clone hpack and fix so they throw with debug info as their errors contain no info :(
}
}
private List<Http2Header> decodeImpl(Decoder decoder, DataWrapper data, int streamId) throws IOException {
List<Http2Header> headers = new ArrayList<>();
byte[] bytes = data.createByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
//keep this synchronized very very small...
synchronized(decoder) {
decoder.decode(in, (n, v, s) -> addToHeaders(headers, n, v, s, streamId));
decoder.endHeaderBlock();
return headers;
}
}
private Object addToHeaders(List<Http2Header> headers, byte[] name, byte[] value, boolean sensitive, int streamId) {
String h = new String(name);
String v = new String(value);
if(!h.equals(h.toLowerCase()))
throw new StreamException(ParseFailReason.HEADER_NOT_LOWER_CASE, streamId, "header="+h+" was not lower case in stream="+streamId);
headers.add(new Http2Header(h, v));
return null;
}
}