use of com.webpieces.http2.api.dto.lowlevel.lib.Http2Frame in project webpieces by deanhiller.
the class HeaderEncoding method createHeaderFrames.
private List<Http2Frame> createHeaderFrames(HasHeaderFragment initialFrame, List<Http2Header> headers, Encoder encoder, long maxFrameSize) {
int maxSize = (int) maxFrameSize;
if (maxFrameSize > Integer.MAX_VALUE)
throw new IllegalStateException("max frame size too large for this hpack library");
List<Http2Frame> headerFrames = new LinkedList<>();
DataWrapper serializedHeaders = serializeHeaders(encoder, headers);
HasHeaderFragment currentFrame = initialFrame;
HasHeaderFragment lastFrame = currentFrame;
DataWrapper dataLeftOver = serializedHeaders;
while (dataLeftOver.getReadableSize() > 0) {
lastFrame = currentFrame;
int splitSize = Math.min(dataLeftOver.getReadableSize(), maxSize);
List<? extends DataWrapper> split = dataGen.split(dataLeftOver, splitSize);
DataWrapper fragment = split.get(0);
currentFrame.setHeaderFragment(fragment);
headerFrames.add(currentFrame);
currentFrame = new ContinuationFrame();
currentFrame.setStreamId(initialFrame.getStreamId());
dataLeftOver = split.get(1);
}
// last frame is currentFrame so set end header
lastFrame.setEndHeaders(true);
return headerFrames;
}
use of com.webpieces.http2.api.dto.lowlevel.lib.Http2Frame in project webpieces by deanhiller.
the class DataMarshaller method marshal.
@Override
public DataWrapper marshal(Http2Frame frame) {
DataFrame castFrame = (DataFrame) frame;
int paddingSize = castFrame.getPadding().getReadableSize();
if (frame.getStreamId() == 0)
throw new ConnectionException(CancelReasonCode.INVALID_STREAM_ID, frame.getStreamId(), "data frame had invalid stream id=" + frame.getStreamId());
byte value = (byte) 0x0;
if (castFrame.isEndOfStream())
value |= 0x1;
if (paddingSize > 0)
value |= 0x8;
DataWrapper dataPayload = PaddingUtil.padDataIfNeeded(castFrame.getData(), castFrame.getPadding());
return super.marshalFrame(frame, value, dataPayload);
}
use of com.webpieces.http2.api.dto.lowlevel.lib.Http2Frame in project webpieces by deanhiller.
the class TestS4FrameSizeAndHeaders method testSection4_3InterleavedFrames.
/**
* Each header block is processed as a discrete unit. Header blocks
* MUST be transmitted as a contiguous sequence of frames, with no interleaved
* frames of any other type or from any other stream. The last frame in a
* sequence of HEADERS or CONTINUATION frames has the END_HEADERS flag set. The
* last frame in a sequence of PUSH_PROMISE or CONTINUATION frames has the
* END_HEADERS flag set. This allows a header block to be logically equivalent to a single frame.
*
* Header block fragments can only be sent as the payload of HEADERS, PUSH_PROMISE, or
* CONTINUATION frames because these frames carry data that can modify the
* compression context maintained by a receiver. An endpoint receiving
* HEADERS, PUSH_PROMISE, or CONTINUATION frames needs to reassemble header
* blocks and perform decompression even if the frames are to be discarded. A receiver
* MUST terminate the connection with a connection error (Section 5.4.1) of
* type COMPRESSION_ERROR if it does not decompress a header block.
*/
@Test
public void testSection4_3InterleavedFrames() {
List<Http2Frame> frames = createInterleavedFrames();
// for this test, need interleaved
Assert.assertTrue(frames.size() >= 3);
mockChannel.sendFrame(frames.get(0));
mockChannel.sendFrame(frames.get(1));
// no request comes in
Assert.assertEquals(0, mockListener.getNumRequestsThatCameIn());
Assert.assertTrue(mockListener.isClosed());
// remote receives goAway
GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear();
Assert.assertEquals(Http2ErrorCode.PROTOCOL_ERROR, goAway.getKnownErrorCode());
DataWrapper debugData = goAway.getDebugData();
String msg = debugData.createStringFromUtf8(0, debugData.getReadableSize());
Assert.assertTrue(msg.contains("Headers/continuations from two different streams per spec cannot be interleaved. "));
Assert.assertTrue(mockChannel.isClosed());
}
Aggregations