package com.firefly.codec.http2.encode; import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; import com.firefly.codec.http2.frame.DataFrame; import com.firefly.codec.http2.frame.Flags; import com.firefly.codec.http2.frame.Frame; import com.firefly.codec.http2.frame.FrameType; import com.firefly.utils.io.BufferUtils; import com.firefly.utils.lang.Pair; public class DataGenerator { private final HeaderGenerator headerGenerator; public DataGenerator(HeaderGenerator headerGenerator) { this.headerGenerator = headerGenerator; } public Pair<Integer, List<ByteBuffer>> generate(DataFrame frame, int maxLength) { return generateData(frame.getStreamId(), frame.getData(), frame.isEndStream(), maxLength); } public Pair<Integer, List<ByteBuffer>> generateData(int streamId, ByteBuffer data, boolean last, int maxLength) { if (streamId < 0) throw new IllegalArgumentException("Invalid stream id: " + streamId); List<ByteBuffer> list = new LinkedList<>(); if (streamId < 0) throw new IllegalArgumentException("Invalid stream id: " + streamId); int dataLength = data.remaining(); int maxFrameSize = headerGenerator.getMaxFrameSize(); int length = Math.min(dataLength, Math.min(maxFrameSize, maxLength)); if (length == dataLength) { generateFrame(streamId, data, last, list); } else { int limit = data.limit(); int newLimit = data.position() + length; data.limit(newLimit); ByteBuffer slice = data.slice(); data.position(newLimit); data.limit(limit); generateFrame(streamId, slice, false, list); } return new Pair<>(length, list); } private void generateFrame(int streamId, ByteBuffer data, boolean last, List<ByteBuffer> list) { int length = data.remaining(); int flags = Flags.NONE; if (last) flags |= Flags.END_STREAM; ByteBuffer header = headerGenerator.generate(FrameType.DATA, Frame.HEADER_LENGTH + length, length, flags, streamId); BufferUtils.flipToFlush(header, 0); list.add(header); if (data.remaining() > 0) list.add(data); } }