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 }