1 module hunt.http.codec.http.encode.PushPromiseGenerator;
2 
3 import hunt.collection;
4 
5 import hunt.http.codec.http.frame.Flags;
6 import hunt.http.codec.http.frame.Frame;
7 import hunt.http.codec.http.frame.FrameType;
8 import hunt.http.codec.http.frame.PushPromiseFrame;
9 import hunt.http.codec.http.hpack.HpackEncoder;
10 import hunt.http.HttpMetaData;
11 
12 import hunt.http.codec.http.encode.FrameGenerator;
13 import hunt.http.codec.http.encode.HeaderGenerator;
14 
15 import hunt.Exceptions;
16 
17 import std.conv;
18 
19 /**
20 */
21 class PushPromiseGenerator :FrameGenerator {
22 	private HpackEncoder encoder;
23 
24 	this(HeaderGenerator headerGenerator, HpackEncoder encoder) {
25 		super(headerGenerator);
26 		this.encoder = encoder;
27 	}
28 
29 	override
30 	List!(ByteBuffer) generate(Frame frame) {
31 		PushPromiseFrame pushPromiseFrame = cast(PushPromiseFrame) frame;
32 		return generatePushPromise(pushPromiseFrame.getStreamId(), pushPromiseFrame.getPromisedStreamId(),
33 				pushPromiseFrame.getMetaData());
34 	}
35 
36 	List!(ByteBuffer) generatePushPromise(int streamId, int promisedStreamId, HttpMetaData metaData) {
37 		if (streamId < 0)
38 			throw new IllegalArgumentException("Invalid stream id: " ~ streamId.to!string);
39 		if (promisedStreamId < 0)
40 			throw new IllegalArgumentException("Invalid promised stream id: " ~ promisedStreamId.to!string);
41 
42 		List!(ByteBuffer) list = new LinkedList!(ByteBuffer)();
43 		int maxFrameSize = getMaxFrameSize();
44 		// The promised streamId space.
45 		int extraSpace = 4;
46 		maxFrameSize -= extraSpace;
47 
48 		ByteBuffer hpacked = BufferUtils.allocate(maxFrameSize);
49 		BufferUtils.clearToFill(hpacked);
50 		encoder.encode(hpacked, metaData);
51 		int hpackedLength = hpacked.position();
52 		BufferUtils.flipToFlush(hpacked, 0);
53 
54 		int length = hpackedLength + extraSpace;
55 		int flags = Flags.END_HEADERS;
56 
57 		ByteBuffer header = generateHeader(FrameType.PUSH_PROMISE, length, flags, streamId);
58 		header.put!int(promisedStreamId);
59 		BufferUtils.flipToFlush(header, 0);
60 
61 		list.add(header);
62 		list.add(hpacked);
63 		return list;
64 	}
65 }