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

com.firefly.codec.http2.encode.HeadersGenerator Maven / Gradle / Ivy

There is a newer version: 4.0.3.2
Show newest version
package com.firefly.codec.http2.encode;

import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;

import com.firefly.codec.http2.frame.Flags;
import com.firefly.codec.http2.frame.Frame;
import com.firefly.codec.http2.frame.FrameType;
import com.firefly.codec.http2.frame.HeadersFrame;
import com.firefly.codec.http2.frame.PriorityFrame;
import com.firefly.codec.http2.hpack.HpackEncoder;
import com.firefly.codec.http2.model.MetaData;
import com.firefly.utils.io.BufferUtils;

public class HeadersGenerator extends FrameGenerator {
	private final HpackEncoder encoder;
	private final int maxHeaderBlockFragment;
	private final PriorityGenerator priorityGenerator;

	public HeadersGenerator(HeaderGenerator headerGenerator, HpackEncoder encoder) {
		this(headerGenerator, encoder, 0);
	}

	public HeadersGenerator(HeaderGenerator headerGenerator, HpackEncoder encoder, int maxHeaderBlockFragment) {
		super(headerGenerator);
		this.encoder = encoder;
		this.maxHeaderBlockFragment = maxHeaderBlockFragment;
		this.priorityGenerator = new PriorityGenerator(headerGenerator);
	}

	@Override
	public List generate(Frame frame) {
		HeadersFrame headersFrame = (HeadersFrame) frame;
		return generateHeaders(headersFrame.getStreamId(), headersFrame.getMetaData(), headersFrame.getPriority(),
				headersFrame.isEndStream());
	}

	public List generateHeaders(int streamId, MetaData metaData, PriorityFrame priority,
			boolean endStream) {
		List list = new LinkedList<>();
		if (streamId < 0)
			throw new IllegalArgumentException("Invalid stream id: " + streamId);

		int flags = Flags.NONE;

		if (priority != null)
			flags = Flags.PRIORITY;

		int maxFrameSize = getMaxFrameSize();
		ByteBuffer hpacked = ByteBuffer.allocate(maxFrameSize);
		BufferUtils.clearToFill(hpacked);
		encoder.encode(hpacked, metaData);
		int hpackedLength = hpacked.position();
		BufferUtils.flipToFlush(hpacked, 0);

		// Split into CONTINUATION frames if necessary.
		if (maxHeaderBlockFragment > 0 && hpackedLength > maxHeaderBlockFragment) {
			if (endStream)
				flags |= Flags.END_STREAM;

			int length = maxHeaderBlockFragment;
			if (priority != null)
				length += PriorityFrame.PRIORITY_LENGTH;

			ByteBuffer header = generateHeader(FrameType.HEADERS, length, flags, streamId);
			generatePriority(header, priority);
			BufferUtils.flipToFlush(header, 0);
			list.add(header);

			hpacked.limit(maxHeaderBlockFragment);
			list.add(hpacked.slice());

			int position = maxHeaderBlockFragment;
			int limit = position + maxHeaderBlockFragment;
			while (limit < hpackedLength) {
				hpacked.position(position).limit(limit);
				header = generateHeader(FrameType.CONTINUATION, maxHeaderBlockFragment, Flags.NONE, streamId);
				BufferUtils.flipToFlush(header, 0);
				list.add(header);
				list.add(hpacked.slice());
				position += maxHeaderBlockFragment;
				limit += maxHeaderBlockFragment;
			}

			hpacked.position(position).limit(hpackedLength);
			header = generateHeader(FrameType.CONTINUATION, hpacked.remaining(), Flags.END_HEADERS, streamId);
			BufferUtils.flipToFlush(header, 0);
			list.add(header);
			list.add(hpacked);
		} else {
			flags |= Flags.END_HEADERS;
			if (endStream)
				flags |= Flags.END_STREAM;

			int length = hpackedLength;
			if (priority != null)
				length += PriorityFrame.PRIORITY_LENGTH;

			ByteBuffer header = generateHeader(FrameType.HEADERS, length, flags, streamId);
			generatePriority(header, priority);
			BufferUtils.flipToFlush(header, 0);
			list.add(header);
			list.add(hpacked);
		}
		return list;
	}

	private void generatePriority(ByteBuffer header, PriorityFrame priority) {
		if (priority != null) {
			priorityGenerator.generatePriorityBody(header, priority.getStreamId(), priority.getParentStreamId(),
					priority.getWeight(), priority.isExclusive());
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy