1 module hunt.http.codec.http.encode.Http2Generator;
2 
3 import hunt.http.codec.http.frame.DataFrame;
4 import hunt.http.codec.http.frame.Frame;
5 import hunt.http.codec.http.frame.FrameType;
6 import hunt.http.codec.http.hpack.HpackEncoder;
7 
8 import hunt.http.codec.http.encode.DataGenerator;
9 import hunt.http.codec.http.encode.DisconnectGenerator;
10 import hunt.http.codec.http.encode.FrameGenerator;
11 import hunt.http.codec.http.encode.HeaderGenerator;
12 import hunt.http.codec.http.encode.HeadersGenerator;
13 import hunt.http.codec.http.encode.GoAwayGenerator;
14 import hunt.http.codec.http.encode.PingGenerator;
15 import hunt.http.codec.http.encode.PriorityGenerator;
16 import hunt.http.codec.http.encode.PrefaceGenerator;
17 import hunt.http.codec.http.encode.PushPromiseGenerator;
18 import hunt.http.codec.http.encode.ResetGenerator;
19 import hunt.http.codec.http.encode.SettingsGenerator;
20 import hunt.http.codec.http.encode.WindowUpdateGenerator;
21 
22 import hunt.io.ByteBuffer;
23 import hunt.collection.List;
24 import hunt.logging;
25 
26 import std.typecons;
27 
28 /**
29 */
30 class Http2Generator {
31 	private HeaderGenerator headerGenerator;
32 	private HpackEncoder hpackEncoder;
33 	private FrameGenerator[FrameType] generators;
34 	private DataGenerator dataGenerator;
35 
36 	this() {
37 		this(4096, 0);
38 	}
39 
40 	this(int maxDynamicTableSize, int maxHeaderBlockFragment) {
41 
42         version (HUNT_DEBUG) trace("Initializing Http2Generator");
43 
44 		headerGenerator = new HeaderGenerator();
45 		hpackEncoder = new HpackEncoder(maxDynamicTableSize);
46 
47 		// this.generators = new FrameGenerator[FrameType.values().length];
48 		this.generators[FrameType.HEADERS] = new HeadersGenerator(headerGenerator, hpackEncoder, maxHeaderBlockFragment);
49 		this.generators[FrameType.PRIORITY] = new PriorityGenerator(headerGenerator);
50 		this.generators[FrameType.RST_STREAM] = new ResetGenerator(headerGenerator);
51 		this.generators[FrameType.SETTINGS] = new SettingsGenerator(headerGenerator);
52 		this.generators[FrameType.PUSH_PROMISE] = new PushPromiseGenerator(headerGenerator, hpackEncoder);
53 		this.generators[FrameType.PING] = new PingGenerator(headerGenerator);
54 		this.generators[FrameType.GO_AWAY] = new GoAwayGenerator(headerGenerator);
55 		this.generators[FrameType.WINDOW_UPDATE] = new WindowUpdateGenerator(headerGenerator);
56 		this.generators[FrameType.CONTINUATION] = null; // Never generated explicitly.
57 		this.generators[FrameType.PREFACE] = new PrefaceGenerator();
58 		this.generators[FrameType.DISCONNECT] = new DisconnectGenerator();
59 
60 		this.dataGenerator = new DataGenerator(headerGenerator);
61 	}
62 
63 	void setHeaderTableSize(int headerTableSize) {
64 		hpackEncoder.setRemoteMaxDynamicTableSize(headerTableSize);
65 	}
66 
67 	void setMaxFrameSize(int maxFrameSize) {
68 		headerGenerator.setMaxFrameSize(maxFrameSize);
69 	}
70 
71 	// 
72 	T getControlGenerator(T)(FrameType type) if(is(T : FrameGenerator)) {
73 		return cast(T) this.generators[type];
74 	}
75 	
76 	List!(ByteBuffer) control(Frame frame) {
77 		return generators[frame.getType()].generate(frame);
78 	}
79 
80 	/**
81 	 * Encode data frame to binary codes
82 	 * @param frame DataFrame
83 	 * @param maxLength The max length of DataFrame
84 	 * @return A pair of encoding result. The first field is frame length which contains header frame and data frame.
85 	 * The second field is binary codes.
86 	 */
87 	Tuple!(int, List!(ByteBuffer)) data(DataFrame frame, int maxLength) {
88 		return dataGenerator.generate(frame, maxLength);
89 	}
90 	
91 	void setMaxHeaderListSize(int value) {
92         hpackEncoder.setMaxHeaderListSize(value);
93     }
94 }