1 module hunt.http.codec.http.encode.GoAwayGenerator;
2 
3 import hunt.http.codec.http.frame.Flags;
4 import hunt.http.codec.http.frame.Frame;
5 import hunt.http.codec.http.frame.FrameType;
6 import hunt.http.codec.http.frame.GoAwayFrame;
7 
8 import hunt.http.codec.http.encode.FrameGenerator;
9 import hunt.http.codec.http.encode.HeaderGenerator;
10 
11 import hunt.collection;
12 import hunt.Exceptions;
13 
14 import std.conv;
15 
16 
17 /**
18 */
19 class GoAwayGenerator :FrameGenerator {
20     this(HeaderGenerator headerGenerator) {
21         super(headerGenerator);
22     }
23 
24     override
25     List!(ByteBuffer) generate(Frame frame) {
26         GoAwayFrame goAwayFrame = cast(GoAwayFrame) frame;
27         return Collections.singletonList(generateGoAway(goAwayFrame.getLastStreamId(), goAwayFrame.getError(), goAwayFrame.getPayload()));
28     }
29 
30     ByteBuffer generateGoAway(int lastStreamId, int error, byte[] payload) {
31         if (lastStreamId < 0)
32             throw new IllegalArgumentException("Invalid last stream id: " ~ lastStreamId.to!string());
33 
34         // The last streamId + the error code.
35         int fixedLength = 4 + 4;
36 
37         // Make sure we don't exceed the default frame max length.
38         int maxPayloadLength = Frame.DEFAULT_MAX_LENGTH - fixedLength;
39         if (payload != null && payload.length > maxPayloadLength)
40             payload = payload[0 .. maxPayloadLength];
41 
42         int length = fixedLength + (payload != null ? cast(int)payload.length : 0);
43         ByteBuffer header = generateHeader(FrameType.GO_AWAY, length, Flags.NONE, 0);
44 
45         header.put!int(lastStreamId);
46         header.put!int(error);
47 
48         if (payload != null) {
49             header.put(payload);
50         }
51 
52         BufferUtils.flipToFlush(header, 0);
53         return header;
54     }
55 }