1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http2.generator;
20
21 import java.nio.ByteBuffer;
22
23 import org.eclipse.jetty.http2.Flags;
24 import org.eclipse.jetty.http2.frames.DataFrame;
25 import org.eclipse.jetty.http2.frames.Frame;
26 import org.eclipse.jetty.http2.frames.FrameType;
27 import org.eclipse.jetty.io.ByteBufferPool;
28 import org.eclipse.jetty.util.BufferUtil;
29
30 public class DataGenerator
31 {
32 private final HeaderGenerator headerGenerator;
33
34 public DataGenerator(HeaderGenerator headerGenerator)
35 {
36 this.headerGenerator = headerGenerator;
37 }
38
39 public void generate(ByteBufferPool.Lease lease, DataFrame frame, int maxLength)
40 {
41 generateData(lease, frame.getStreamId(), frame.getData(), frame.isEndStream(), maxLength);
42 }
43
44 public void generateData(ByteBufferPool.Lease lease, int streamId, ByteBuffer data, boolean last, int maxLength)
45 {
46 if (streamId < 0)
47 throw new IllegalArgumentException("Invalid stream id: " + streamId);
48
49 int dataLength = data.remaining();
50 int maxFrameSize = headerGenerator.getMaxFrameSize();
51 if (dataLength <= maxLength && dataLength <= maxFrameSize)
52 {
53
54 generateFrame(lease, streamId, data, last);
55 return;
56 }
57
58
59
60 int length = Math.min(maxLength, dataLength);
61 int frames = length / maxFrameSize;
62 if (frames * maxFrameSize != length)
63 ++frames;
64
65 int begin = data.position();
66 int end = data.limit();
67 for (int i = 1; i <= frames; ++i)
68 {
69 int limit = begin + Math.min(maxFrameSize * i, length);
70 data.limit(limit);
71 ByteBuffer slice = data.slice();
72 data.position(limit);
73 generateFrame(lease, streamId, slice, i == frames && last && limit == end);
74 }
75 data.limit(end);
76 }
77
78 private void generateFrame(ByteBufferPool.Lease lease, int streamId, ByteBuffer data, boolean last)
79 {
80 int length = data.remaining();
81
82 int flags = Flags.NONE;
83 if (last)
84 flags |= Flags.END_STREAM;
85
86 ByteBuffer header = headerGenerator.generate(lease, FrameType.DATA, Frame.HEADER_LENGTH + length, length, flags, streamId);
87
88 BufferUtil.flipToFlush(header, 0);
89 lease.append(header, true);
90
91 lease.append(data, false);
92 }
93 }