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.http.MetaData;
24 import org.eclipse.jetty.http2.Flags;
25 import org.eclipse.jetty.http2.frames.Frame;
26 import org.eclipse.jetty.http2.frames.FrameType;
27 import org.eclipse.jetty.http2.frames.HeadersFrame;
28 import org.eclipse.jetty.http2.frames.PriorityFrame;
29 import org.eclipse.jetty.http2.hpack.HpackEncoder;
30 import org.eclipse.jetty.io.ByteBufferPool;
31 import org.eclipse.jetty.util.BufferUtil;
32
33 public class HeadersGenerator extends FrameGenerator
34 {
35 private final HpackEncoder encoder;
36 private final int maxHeaderBlockFragment;
37 private final PriorityGenerator priorityGenerator;
38
39 public HeadersGenerator(HeaderGenerator headerGenerator, HpackEncoder encoder)
40 {
41 this(headerGenerator, encoder, 0);
42 }
43
44 public HeadersGenerator(HeaderGenerator headerGenerator, HpackEncoder encoder, int maxHeaderBlockFragment)
45 {
46 super(headerGenerator);
47 this.encoder = encoder;
48 this.maxHeaderBlockFragment = maxHeaderBlockFragment;
49 this.priorityGenerator = new PriorityGenerator(headerGenerator);
50 }
51
52 @Override
53 public void generate(ByteBufferPool.Lease lease, Frame frame)
54 {
55 HeadersFrame headersFrame = (HeadersFrame)frame;
56 generateHeaders(lease, headersFrame.getStreamId(), headersFrame.getMetaData(), headersFrame.getPriority(), headersFrame.isEndStream());
57 }
58
59 public void generateHeaders(ByteBufferPool.Lease lease, int streamId, MetaData metaData, PriorityFrame priority, boolean endStream)
60 {
61 if (streamId < 0)
62 throw new IllegalArgumentException("Invalid stream id: " + streamId);
63
64 int flags = Flags.NONE;
65
66 if (priority != null)
67 flags = Flags.PRIORITY;
68
69 int maxFrameSize = getMaxFrameSize();
70 ByteBuffer hpacked = lease.acquire(maxFrameSize, false);
71 BufferUtil.clearToFill(hpacked);
72 encoder.encode(hpacked, metaData);
73 int hpackedLength = hpacked.position();
74 BufferUtil.flipToFlush(hpacked, 0);
75
76
77 if (maxHeaderBlockFragment > 0 && hpackedLength > maxHeaderBlockFragment)
78 {
79 if (endStream)
80 flags |= Flags.END_STREAM;
81
82 int length = maxHeaderBlockFragment;
83 if (priority != null)
84 length += PriorityFrame.PRIORITY_LENGTH;
85
86 ByteBuffer header = generateHeader(lease, FrameType.HEADERS, length, flags, streamId);
87 generatePriority(header, priority);
88 BufferUtil.flipToFlush(header, 0);
89 lease.append(header, true);
90
91 hpacked.limit(maxHeaderBlockFragment);
92 lease.append(hpacked.slice(), false);
93
94 int position = maxHeaderBlockFragment;
95 int limit = position + maxHeaderBlockFragment;
96 while (limit < hpackedLength)
97 {
98 hpacked.position(position).limit(limit);
99 header = generateHeader(lease, FrameType.CONTINUATION, maxHeaderBlockFragment, Flags.NONE, streamId);
100 BufferUtil.flipToFlush(header, 0);
101 lease.append(header, true);
102 lease.append(hpacked.slice(), false);
103 position += maxHeaderBlockFragment;
104 limit += maxHeaderBlockFragment;
105 }
106
107 hpacked.position(position).limit(hpackedLength);
108 header = generateHeader(lease, FrameType.CONTINUATION, hpacked.remaining(), Flags.END_HEADERS, streamId);
109 BufferUtil.flipToFlush(header, 0);
110 lease.append(header, true);
111 lease.append(hpacked, true);
112 }
113 else
114 {
115 flags |= Flags.END_HEADERS;
116 if (endStream)
117 flags |= Flags.END_STREAM;
118
119 int length = hpackedLength;
120 if (priority != null)
121 length += PriorityFrame.PRIORITY_LENGTH;
122
123 ByteBuffer header = generateHeader(lease, FrameType.HEADERS, length, flags, streamId);
124 generatePriority(header, priority);
125 BufferUtil.flipToFlush(header, 0);
126 lease.append(header, true);
127 lease.append(hpacked, true);
128 }
129 }
130
131 private void generatePriority(ByteBuffer header, PriorityFrame priority)
132 {
133 if (priority != null)
134 {
135 priorityGenerator.generatePriorityBody(header, priority.getStreamId(),
136 priority.getParentStreamId(), priority.getWeight(), priority.isExclusive());
137 }
138 }
139 }