All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.firefly.codec.http2.decode.ContinuationBodyParser Maven / Gradle / Ivy

There is a newer version: 5.0.0-dev6
Show newest version
package com.firefly.codec.http2.decode;

import java.nio.ByteBuffer;

import com.firefly.codec.http2.frame.ErrorCode;
import com.firefly.codec.http2.frame.Flags;
import com.firefly.codec.http2.frame.HeadersFrame;
import com.firefly.codec.http2.model.MetaData;

public class ContinuationBodyParser extends BodyParser {
	private final HeaderBlockParser headerBlockParser;
	private final HeaderBlockFragments headerBlockFragments;
	private State state = State.PREPARE;
	private int length;

	public ContinuationBodyParser(HeaderParser headerParser, Parser.Listener listener,
			HeaderBlockParser headerBlockParser, HeaderBlockFragments headerBlockFragments) {
		super(headerParser, listener);
		this.headerBlockParser = headerBlockParser;
		this.headerBlockFragments = headerBlockFragments;
	}

	@Override
	protected void emptyBody(ByteBuffer buffer) {
		if (hasFlag(Flags.END_HEADERS))
			onHeaders();
	}

	@Override
	public boolean parse(ByteBuffer buffer) {
		while (buffer.hasRemaining()) {
			switch (state) {
			case PREPARE: {
				// SPEC: wrong streamId is treated as connection error.
				if (getStreamId() == 0)
					return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_continuation_frame");

				if (getStreamId() != headerBlockFragments.getStreamId())
					return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_continuation_stream");

				length = getBodyLength();
				state = State.FRAGMENT;
				break;
			}
			case FRAGMENT: {
				int remaining = buffer.remaining();
				if (remaining < length) {
					headerBlockFragments.storeFragment(buffer, remaining, false);
					length -= remaining;
					break;
				} else {
					boolean last = hasFlag(Flags.END_HEADERS);
					headerBlockFragments.storeFragment(buffer, length, last);
					reset();
					if (last)
						onHeaders();
					return true;
				}
			}
			default: {
				throw new IllegalStateException();
			}
			}
		}
		return false;
	}

	private void onHeaders() {
		ByteBuffer headerBlock = headerBlockFragments.complete();
		MetaData metaData = headerBlockParser.parse(headerBlock, headerBlock.remaining());
		HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, headerBlockFragments.getPriorityFrame(),
				headerBlockFragments.isEndStream());
		notifyHeaders(frame);
	}

	private void reset() {
		state = State.PREPARE;
		length = 0;
	}

	private enum State {
		PREPARE, FRAGMENT
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy