1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http2.frame;
29
30 import java.nio.ByteBuffer;
31 import java.nio.charset.StandardCharsets;
32
33 import org.apache.hc.core5.http2.H2Error;
34 import org.apache.hc.core5.http2.config.H2Setting;
35 import org.apache.hc.core5.util.Args;
36
37
38
39
40
41
42
43 public abstract class FrameFactory {
44
45 public RawFrame createSettings(final H2Setting... settings) {
46 final ByteBuffer payload = ByteBuffer.allocate(settings.length * 12);
47 for (final H2Setting setting: settings) {
48 payload.putShort((short) setting.getCode());
49 payload.putInt(setting.getValue());
50 }
51 payload.flip();
52 return new RawFrame(FrameType.SETTINGS.getValue(), 0, 0, payload);
53 }
54
55 public RawFrame createSettingsAck() {
56 return new RawFrame(FrameType.SETTINGS.getValue(), FrameFlag.ACK.getValue(), 0, null);
57 }
58
59 public RawFrame createResetStream(final int streamId, final H2Error error) {
60 Args.notNull(error, "Error");
61 return createResetStream(streamId, error.getCode());
62 }
63
64 public RawFrame createResetStream(final int streamId, final int code) {
65 Args.positive(streamId, "Stream id");
66 final ByteBuffer payload = ByteBuffer.allocate(4);
67 payload.putInt(code);
68 payload.flip();
69 return new RawFrame(FrameType.RST_STREAM.getValue(), 0, streamId, payload);
70 }
71
72 public RawFrame createPing(final ByteBuffer opaqueData) {
73 Args.notNull(opaqueData, "Opaque data");
74 Args.check(opaqueData.remaining() == 8, "Opaque data length must be equal 8");
75 return new RawFrame(FrameType.PING.getValue(), 0, 0, opaqueData);
76 }
77
78 public RawFrame createPingAck(final ByteBuffer opaqueData) {
79 Args.notNull(opaqueData, "Opaque data");
80 Args.check(opaqueData.remaining() == 8, "Opaque data length must be equal 8");
81 return new RawFrame(FrameType.PING.getValue(), FrameFlag.ACK.value, 0, opaqueData);
82 }
83
84 public RawFrame createGoAway(final int lastStream, final H2Error error, final String message) {
85 Args.notNegative(lastStream, "Last stream id");
86 final byte[] debugData = message != null ? message.getBytes(StandardCharsets.US_ASCII) : null;
87 final ByteBuffer payload = ByteBuffer.allocate(8 + (debugData != null ? debugData.length : 0));
88 payload.putInt(lastStream);
89 payload.putInt(error.getCode());
90 if (debugData != null) {
91 payload.put(debugData);
92 }
93 payload.flip();
94 return new RawFrame(FrameType.GOAWAY.getValue(), 0, 0, payload);
95 }
96
97 public abstract RawFrame createHeaders(int streamId, ByteBuffer payload, boolean endHeaders, boolean endStream);
98
99 public abstract RawFrame createContinuation(int streamId, ByteBuffer payload, boolean endHeaders);
100
101 public abstract RawFrame createPushPromise(int streamId, ByteBuffer payload, boolean endHeaders);
102
103 public abstract RawFrame createData(int streamId, ByteBuffer payload, boolean endStream);
104
105 public RawFrame createWindowUpdate(final int streamId, final int increment) {
106 Args.notNegative(streamId, "Stream id");
107 Args.positive(increment, "Increment");
108 final ByteBuffer payload = ByteBuffer.allocate(4);
109 payload.putInt(increment);
110 payload.flip();
111 return new RawFrame(FrameType.WINDOW_UPDATE.getValue(), 0, streamId, payload);
112 }
113
114 }