1 /**
2  * Frame
3  * 
4  * Copyright:
5  * (C) 2012-2015 Tatsuhiro Tsujikawa
6  * (C) 2014-2015 Etienne Cimon
7  *
8  * License: 
9  * Distributed under the terms of the MIT license with an additional section 1.2 of the curl/libcurl project. 
10  * Consult the provided LICENSE.md file for details
11  */
12 module libhttp2.frame;
13 import libhttp2.constants;
14 import libhttp2.types;
15 import libhttp2.stream;
16 import libhttp2.buffers;
17 import libhttp2.huffman;
18 import libhttp2.helpers;
19 import libhttp2.deflater;
20 import std.algorithm : min, max;
21 import std.conv : to;
22 import core.stdc..string : memcpy;
23 
24 struct FrameHeader 
25 {
26 	/// The length after this header
27 	uint length;
28 	FrameType type;
29 	FrameFlags flags;
30 	int stream_id;
31 
32 	ubyte reserved = 0;
33 
34 	this(uint _length, FrameType _type, FrameFlags _flags, int _stream_id) 
35 	{
36 		length = _length;
37 		type = _type;
38 		flags = _flags;
39 		stream_id = _stream_id;
40 	}
41 
42 	// unpack buf into FrameHeader
43 	this(in ubyte* buf) {
44 		unpack(buf);
45 	}
46 
47 	void unpack(in ubyte* buf) {
48 		length = read!uint(buf) >> 8;
49 		type = cast(FrameType) buf[3];
50 		flags = cast(FrameFlags) buf[4];
51 		stream_id = read!uint(&buf[5]) & STREAM_ID_MASK;
52 	}
53 
54 	void unpack(in ubyte[] buf) {
55 		length = read!uint(buf) >> 8;
56 		type = cast(FrameType)buf[3];
57 		flags = cast(FrameFlags)buf[4];
58 		stream_id = read!uint(buf[5 .. $]) & STREAM_ID_MASK;
59 	}
60 
61 	// pack FrameHeader into buf
62 	void pack(ubyte[] buf) {
63 		write!uint(buf, cast(uint)(length << 8));
64 		buf[3] = cast(ubyte) type;
65 		buf[4] = cast(ubyte) flags;
66 		write!uint(buf[5 .. $], cast(uint)stream_id);
67 		/* ignore hd.reserved for now */
68 	}
69 
70 	/*
71 	 * Call this function after payload was serialized, but not before
72 	 * changing buf.pos and serializing frame header.
73 	 *
74 	 * This function assumes bufs.cur points to the last buf chain of the
75 	 * frame(s).
76 	 *
77 	 * This function serializes frame header for HEADERS/PUSH_PROMISE and
78 	 * handles their successive CONTINUATION frames.
79 	 *
80 	 * We don't process any padding here.
81 	 */
82 	void packShared(Buffers bufs) 
83 	{
84 		Buffer* buf;
85 		Buffers.Chain ci;
86 		Buffers.Chain ce;
87 
88 		buf = &bufs.head.buf;
89 		length = buf.length;
90 		
91 		LOGF("send: HEADERS/PUSH_PROMISE, payloadlen=%d", length);
92 		
93 		/* We have multiple frame buffers, which means one or more
94 	       CONTINUATION frame is involved. Remove END_HEADERS flag from the
95 	       first frame. */
96 		if (bufs.head != bufs.cur) {
97 			flags &= ~cast(int)FrameFlags.END_HEADERS;
98 		}
99 		
100 		buf.pos -= FRAME_HDLEN;
101 		pack((*buf)[]);
102 		
103 		if (bufs.head != bufs.cur) {
104 			/* 2nd and later frames are CONTINUATION frames. */
105 			type = FrameType.CONTINUATION;
106 			/* We don't have no flags except for last CONTINUATION */
107 			flags = FrameFlags.NONE;
108 			
109 			ce = bufs.cur;
110 			
111 			for (ci = bufs.head.next; ci != ce; ci = ci.next) {
112 				buf = &ci.buf;
113 				
114 				length = buf.length;
115 				
116 				LOGF("send: int CONTINUATION, payloadlen=%d", length);
117 				
118 				buf.pos -= FRAME_HDLEN;
119 				pack((*buf)[]);
120 			}
121 			
122 			buf = &ci.buf;
123 			length = buf.length;
124 			/* Set END_HEADERS flag for last CONTINUATION */
125 			flags = FrameFlags.END_HEADERS;
126 			
127 			LOGF("send: last CONTINUATION, payloadlen=%d", length);
128 			
129 			buf.pos -= FRAME_HDLEN;
130 			pack((*buf)[]);
131 		}
132 	}
133 
134 
135 	void addPad(Buffers bufs, int padlen, bool framehd_only) 
136 	{
137 		Buffer* buf;
138 		
139 		if (padlen == 0) {
140 			LOGF("send: padlen = 0, nothing to do");
141 			
142 			return ;
143 		}
144 		
145 		/*
146 	   * We have arranged bufs like this:
147 	   *
148 	   *  0                   1                   2                   3
149 	   *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
150 	   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 	   * | |Frame header     | Frame payload...                          :
152 	   * +-+-----------------+-------------------------------------------+
153 	   * | |Frame header     | Frame payload...                          :
154 	   * +-+-----------------+-------------------------------------------+
155 	   * | |Frame header     | Frame payload...                          :
156 	   * +-+-----------------+-------------------------------------------+
157 	   *
158 	   * We arranged padding so that it is included in the first frame
159 	   * completely.  For padded frame, we are going to adjust buf.pos of
160 	   * frame which includes padding and serialize (memmove) frame header
161 	   * in the correct position.  Also extends buf.last to include
162 	   * padding.
163 	   */
164 		
165 		buf = &bufs.head.buf;
166 		
167 		assert(buf.available >= cast(size_t)(padlen - 1));
168 		
169 		frameSetPad(buf, padlen, framehd_only);
170 		
171 		length += padlen;
172 		flags |= FrameFlags.PADDED;
173 		
174 		LOGF("send: final payloadlen=%d, padlen=%d", length, padlen);
175 	}
176 
177 	void free(){}
178 }
179 
180 /// The HEADERS frame.  It has the following members:
181 struct Headers
182 {    
183 	FrameHeader hd;
184 	
185 	/// The length of the padding in this frame.  This includes PAD_HIGH and PAD_LOW.
186 	size_t padlen;
187 	
188 	/// The priority specification
189 	PrioritySpec pri_spec;
190 	
191 	/// The header fields.
192 	HeaderField[] hfa;
193 	
194 	/// The category of this HEADERS frame.
195 	HeadersCategory cat;
196 
197 	/*
198 	 * Initializes HEADERS frame |frame| with given values.  |frame| takes
199 	 * ownership of |hfa|, so caller must not free it. If |stream_id| is
200 	 * not assigned yet, it must be -1.
201 	 */
202 	this(FrameFlags flags, int stream_id, HeadersCategory _cat, in PrioritySpec _pri_spec, HeaderField[] _hfa) {
203 		hd = FrameHeader(0, FrameType.HEADERS, flags, stream_id);
204 		padlen = 0;
205 		hfa = _hfa;
206 		cat = _cat;
207 		pri_spec = _pri_spec;
208 	}
209 
210 	void free() {
211 		if (hfa) { hfa.free(); }
212 	}
213 
214 	/*
215 	 * Packs HEADERS frame in wire format and store it in |bufs|.
216 	 * This function expands |bufs| as necessary to store frame.
217 	 *
218 	 * The caller must make sure that bufs.reset() is called before calling this function.
219 	 *
220 	 * hd.length is assigned after length is determined during
221 	 * packing process. CONTINUATION frames are also serialized in this
222 	 * function. This function does not handle padding.
223 	 *
224 	 * This function returns 0 if it succeeds, or returns one of the
225 	 * following negative error codes:
226 	 *
227 	 * ErrorCode.HEADER_COMP
228 	 *     The deflate operation failed.
229 	 */
230 	ErrorCode pack(Buffers bufs, ref Deflater deflater) 
231 	{
232 		size_t hf_offset;
233 		ErrorCode rv;
234 		Buffer* buf;
235 		
236 		assert(bufs.head == bufs.cur);
237 		
238 		hf_offset = blockOffset();
239 		
240 		buf = &bufs.cur.buf;
241 		
242 		buf.pos += hf_offset;
243 		buf.last = buf.pos;
244 		
245 		/* This call will adjust buf.last to the correct position */
246 		rv = deflater.deflate(bufs, hfa);
247 		if (rv == ErrorCode.BUFFER_ERROR)
248 			rv = ErrorCode.HEADER_COMP;
249 
250 		buf.pos -= hf_offset;
251 		
252 		if (rv != 0)
253 			return rv;
254 		
255 		if (hd.flags & FrameFlags.PRIORITY) {
256 			pri_spec.pack((*buf)[]);
257 		}
258 		
259 		padlen = 0;
260 		hd.length = bufs.length;
261 		hd.packShared(bufs);
262 
263 		return ErrorCode.OK;
264 	}
265 
266 	/*
267 	 * Unpacks HEADERS frame byte sequence into this.  This function
268 	 * only unpacks bytes that come before header field and
269 	 * after possible Pad Length field.
270 	 */
271 	void unpack(in ubyte[] payload) {
272 		if (hd.flags & FrameFlags.PRIORITY) {
273 			pri_spec.unpack(payload);
274 		}
275 	}
276 
277 	/*
278 	 * Returns the offset from the HEADERS frame payload where the
279 	 * compressed header block starts. The frame payload does not include
280 	 * frame header.
281 	 */
282 	size_t blockOffset() {
283 		return hd.flags.priorityLength();
284 	}
285 
286 }
287 
288 
289 
290 /// The DATA frame.  The received data is delivered via http2_on_data_chunk_recv_callback
291 struct Data
292 {
293 	FrameHeader hd;
294 	/// The length of the padding in this frame. This includes PAD_HIGH and PAD_LOW.
295 	int padlen;
296 
297 	this(FrameFlags flags, int stream_id) {
298 		/* At this moment, the length of DATA frame is unknown */
299 		hd = FrameHeader(0, FrameType.DATA, flags, stream_id);
300 		padlen = 0;
301 	}
302 	
303 	void free() {}
304 
305 }
306 
307 
308 /// The structure to specify stream dependency.
309 struct PrioritySpec
310 {
311 	/// The stream ID of the stream to depend on. Specifying 0 makes stream not depend any other stream.
312 	int stream_id;
313 	int weight = DEFAULT_WEIGHT;
314 	bool exclusive;
315 
316 	this(in ubyte[] data) {
317 		unpack(data);
318 	}
319 
320 	/**
321 	 * Packs the PrioritySpec in |buf|.  This function assumes |buf| has
322 	 * enough space for serialization.
323 	 */
324 	void pack(ubyte[] buf) {
325 		write!uint(buf, stream_id);
326 		if (exclusive) 
327 			buf[0] |= 0x80;
328 		buf[4] = cast(ubyte)(weight - 1);
329 	}
330 
331 	/**
332 	 * Unpacks the priority specification from payload |payload| of length
333 	 * |payload.length| to |pri_spec|. This function
334 	 * assumes the |payload| contains whole priority specification.
335 	 */
336 	void unpack(in ubyte[] payload) {
337 		stream_id = read!uint(payload) & STREAM_ID_MASK;
338 		exclusive = (payload[0] & 0x80) > 0;
339 		weight = payload[4] + 1;
340 	}
341 	
342 	/**
343 	 * Initializes PrioritySpec with the |stream_id| of the stream to depend
344 	 * on with |weight| and its exclusive flag.  If |exclusive| is
345 	 * true, exclusive flag is set.
346 	 *
347 	 * The |weight| must be in [$(D HTTP2_MIN_WEIGHT), $(D HTTP2_MAX_WEIGHT)], inclusive.
348 	 */
349 	this(int _stream_id, int _weight, bool _exclusive) {
350 		stream_id = _stream_id;
351 		weight = _weight;
352 		exclusive = _exclusive;
353 	}	
354 
355 	void adjustWeight() {
356 		if (weight < MIN_WEIGHT) {
357 			weight = MIN_WEIGHT;
358 		} else if (weight > MAX_WEIGHT) {
359 			weight = MAX_WEIGHT;
360 		}
361 	}
362 }
363 
364 
365 
366 /// The PRIORITY frame.  It has the following members:
367 struct Priority {
368 	FrameHeader hd;
369 	PrioritySpec pri_spec;
370 
371 	this(int stream_id, in PrioritySpec _pri_spec = PrioritySpec.init) 
372 	{
373 		hd = FrameHeader(PRIORITY_SPECLEN, FrameType.PRIORITY, FrameFlags.NONE, stream_id);
374 		pri_spec = _pri_spec;
375 	}
376 	
377 	void free(){}
378 
379 	/*
380 	 * Packs PRIORITY frame |frame| in wire format and store it in
381 	 * |bufs|.
382 	 *
383 	 * The caller must make sure that bufs.reset() is called
384 	 * before calling this function.
385 	 */
386 	void pack(Buffers bufs) {
387 		Buffer* buf;
388 		
389 		assert(bufs.head == bufs.cur);
390 		
391 		buf = &bufs.head.buf;
392 
393 		assert(buf.available >= PRIORITY_SPECLEN);
394 		
395 		buf.pos -= FRAME_HDLEN;
396 		
397 		hd.pack((*buf)[]);
398 		
399 		pri_spec.pack(buf.last[0 .. buf.available]);
400 		
401 		buf.last += PRIORITY_SPECLEN;
402 	}
403 	
404 	/*
405 	 * Unpacks PRIORITY wire format into this.
406 	 */
407 	void unpack(in ubyte[] payload) {
408 		pri_spec = PrioritySpec(payload);
409 	}
410 
411 }
412 
413 /// The RST_STREAM frame.  It has the following members:
414 struct RstStream {	
415 	FrameHeader hd;
416 	FrameError error_code;
417 
418 	this(int stream_id, FrameError _error_code)
419 	{
420 		hd = FrameHeader(4, FrameType.RST_STREAM, FrameFlags.NONE, stream_id);
421 		error_code = _error_code;
422 	}
423 	
424 	void free(){}
425 
426 	/*
427 	 * Packs RST_STREAM frame |frame| in wire frame format and store it in
428 	 * |bufs|.
429 	 *
430 	 * The caller must make sure that bufs.reset() is called
431 	 * before calling this function.
432 	 */
433 	void pack(Buffers bufs) 
434 	{
435 		Buffer* buf;
436 		
437 		assert(bufs.head == bufs.cur);
438 		
439 		buf = &bufs.head.buf;
440 		
441 		assert(buf.available >= 4);
442 		
443 		buf.pos -= FRAME_HDLEN;
444 		
445 		hd.pack((*buf)[]);
446 		
447 		write!uint(buf.last, error_code);
448 		buf.last += 4;
449 	}
450 	
451 	/*
452 	 * Unpacks RST_STREAM frame byte sequence into |frame|.
453 	 */
454 	void unpack(in ubyte[] payload) {
455 		error_code = cast(FrameError)read!uint(payload);
456 	}
457 }
458 
459 /// The SETTINGS frame
460 struct Settings {
461 	FrameHeader hd;
462 	Setting[] iva;
463 
464 	/*
465 	 * Initializes SETTINGS frame |frame| with given values. |frame| takes
466 	 * ownership of |iv|, so caller must not free it. The |flags| are
467 	 * bitwise-OR of one or more of FrameFlags, the only permissible value is ACK.
468 	 */
469 	this(FrameFlags flags, Setting[] _iva) {
470 		// TODO: Allow only FrameFlags.ACK ?
471 		hd = FrameHeader(cast(uint)_iva.length * FRAME_SETTINGS_ENTRY_LENGTH, FrameType.SETTINGS, flags, 0);
472 		iva = _iva;
473 	}
474 	
475 	void free() { if (iva) Mem.free(iva); }
476 
477 
478 	/*
479 	 * Packs SETTINGS frame in wire format and store it in |bufs|.
480 	 *
481 	 * The caller must make sure that bufs.reset() is called
482 	 * before calling this function.
483 	 *
484 	 * This function returns 0 if it succeeds, or returns one of the
485 	 * following negative error codes:
486 	 *
487 	 * ErrorCode.FRAME_SIZE_ERROR
488 	 *     The length of the frame is too large.
489 	 */
490 	ErrorCode pack(Buffers bufs) {
491 		Buffer* buf;
492 		
493 		assert(bufs.head == bufs.cur);
494 		
495 		buf = &bufs.head.buf;
496 		
497 		if (buf.available < cast(size_t) hd.length) {
498 			return ErrorCode.FRAME_SIZE_ERROR;
499 		}
500 
501 		buf.pos -= FRAME_HDLEN;
502 		
503 		hd.pack((*buf)[]);
504 		buf.last += pack(buf.last[0 .. buf.available], iva);
505 		
506 		return ErrorCode.OK;
507 	}
508 
509 	
510 	/*
511 	 * Makes a copy of |_iva| in |iva|.
512 	 */
513 	void unpack(Setting[] _iva) 
514 	{
515 		if (iva) free();
516 
517 		if (_iva.length == 0) {
518 			iva = null;
519 			return;
520 		}
521 
522 		iva = _iva.copy();
523 		
524 	}
525 
526 	void unpack(in ubyte[] payload) {
527 		unpack(iva, payload);
528 	}
529 
530 	/*
531 	 * Unpacks SETTINGS payload into |iva|. The number of entries are
532 	 * assigned to the |niv|. This function allocates enough memory
533 	 * to store the result in |iva|. The caller is responsible to free
534 	 * |iva| after its use.
535 	 */
536 	static void unpack(ref Setting[] iva, in ubyte[] payload) {		
537 		size_t len = payload.length / FRAME_SETTINGS_ENTRY_LENGTH;
538 		
539 		if (len == 0) {
540 			iva = null;
541 			return;
542 		}
543 		
544 		iva = Mem.alloc!(Setting[])(len);
545 
546 		foreach(i, ref iv; iva) {
547 			size_t off = i * FRAME_SETTINGS_ENTRY_LENGTH;
548 			iv.unpack(payload[off .. $]);
549 		}
550 	}
551 
552 	/*
553 	 * Packs the |_iva|, which includes |_iva.length| entries, in the |buf|,
554 	 * assuming the |buf| has at least 8 * |_iva.length| bytes.
555 	 *
556 	 * Returns the number of bytes written into the |buf|.
557 	 */
558 	static int pack(ubyte[] buf, in Setting[] _iva)
559 	{
560 		foreach (ref iv; _iva) {
561 			write!ushort(buf, iv.id);
562 			write!uint(buf[2 .. $], iv.value);
563 			if (FRAME_SETTINGS_ENTRY_LENGTH < buf.length)
564 				buf = buf[FRAME_SETTINGS_ENTRY_LENGTH .. $];
565 		}
566 		return cast(int) (FRAME_SETTINGS_ENTRY_LENGTH * _iva.length);
567 	}
568 
569 }
570 
571 /// The PUSH_PROMISE frame.  
572 struct PushPromise {    
573 	FrameHeader hd;
574 	
575 	/// The length of the padding in this frame.  This includes PAD_HIGH and PAD_LOW.
576 	size_t padlen;
577 	
578 	/// The header fields.
579 	HeaderField[] hfa;
580 	
581 	/// The promised stream ID
582 	int promised_stream_id;
583 	
584 	/// 0
585 	ubyte reserved = 0;
586 	
587 	/*
588 	 * Initializes PUSH_PROMISE frame with given values.  PushPromise
589 	 * takes ownership of |hfa|, so caller must not free it.
590 	 */
591 	this(FrameFlags flags, int stream_id, int _promised_stream_id, HeaderField[] _hfa) {
592 		hd = FrameHeader(0, FrameType.PUSH_PROMISE, flags, stream_id);
593 		hfa = _hfa;
594 		promised_stream_id = _promised_stream_id;
595 	}
596 	
597 	void free() { if (hfa) hfa.free(); }
598 
599 	/*
600 	 * Packs PUSH_PROMISE frame in wire format and store it in
601 	 * |bufs|.  This function expands |bufs| as necessary to store
602 	 * frame.
603 	 *
604 	 * The caller must make sure that bufs.reset() is called
605 	 * before calling this function.
606 	 *
607 	 * frame.hd.length is assigned after length is determined during
608 	 * packing process. CONTINUATION frames are also serialized in this
609 	 * function. This function does not handle padding.
610 	 *
611 	 * This function returns 0 if it succeeds, or returns one of the
612 	 * following negative error codes:
613 	 *
614 	 * ErrorCode.HEADER_COMP
615 	 *     The deflate operation failed.
616 	 */
617 	ErrorCode pack(Buffers bufs, ref Deflater deflater) 
618 	{
619 		size_t hf_offset = 4;
620 		ErrorCode rv;
621 		Buffer* buf;
622 		
623 		assert(bufs.head == bufs.cur);
624 		
625 		buf = &bufs.cur.buf;
626 		
627 		buf.pos += hf_offset;
628 		buf.last = buf.pos;
629 		
630 		/* This call will adjust buf.last to the correct position */
631 		rv = deflater.deflate(bufs, hfa);
632 		
633 		if (rv == ErrorCode.BUFFER_ERROR)
634 			rv = ErrorCode.HEADER_COMP;
635 		
636 		buf.pos -= hf_offset;
637 		
638 		if (rv != 0)
639 			return rv;
640 		
641 		write!uint(buf.pos, promised_stream_id);
642 		
643 		padlen = 0;
644 		hd.length = bufs.length;
645 		
646 		hd.packShared(bufs);
647 		return ErrorCode.OK;
648 	}
649 	
650 	/*
651 	 * Unpacks PUSH_PROMISE frame byte sequence.  This
652 	 * function only unpacks bytes that come before name/value header
653 	 * block and after possible Pad Length field.
654 	 *
655 	 * TODO: handle END_HEADERS flag is not set
656 	 */
657 	void unpack(in ubyte[] payload) {
658 		promised_stream_id = read!uint(payload) & STREAM_ID_MASK;
659 		hfa = null;
660 	}
661 }
662 
663 /// The PING frame.
664 struct Ping {    
665 	FrameHeader hd;
666 	ubyte[8] opaque_data;
667 
668 	/*
669 	 * Initializes PING frame with given values. If the
670 	 * |opaque_data| is not null, it must point to 8 bytes memory region
671 	 * of data. The data pointed by |opaque_data| is copied. It can be
672 	 * null. In this case, 8 bytes null is used.
673 	 */
674 	this(FrameFlags flags, in ubyte[] _opaque_data) {
675 		hd = FrameHeader(8, FrameType.PING, flags, 0);
676 		if (opaque_data.length > 0)
677 			opaque_data[0 .. min(8, _opaque_data.length)] = _opaque_data[0 .. min(8, _opaque_data.length)];
678 		else
679 			opaque_data = null;
680 	}
681 	
682 	void free(){}
683 
684 	/*
685 	 * Packs PING frame in wire format and store it in |bufs|.
686 	 *
687 	 * The caller must make sure that bufs.reset() is called
688 	 * before calling this function.
689 	 */
690 	void pack(Buffers bufs) {
691 		Buffer* buf;
692 		
693 		assert(bufs.head == bufs.cur);
694 		
695 		buf = &bufs.head.buf;
696 		
697 		assert(buf.available >= 8);
698 		
699 		buf.pos -= FRAME_HDLEN;
700 		
701 		hd.pack((*buf)[]);
702 		
703 		memcpy(buf.last, opaque_data.ptr, opaque_data.sizeof);
704 		buf.last += opaque_data.sizeof;
705 
706 	}
707 	
708 	/*
709 	 * Unpacks PING wire format into |frame|.
710 	 */
711 	void unpack(in ubyte[] _opaque_data)
712 	{
713 		if (opaque_data.length > 0)
714 			opaque_data[0 .. min(8, _opaque_data.length)] = _opaque_data[0 .. min(8, _opaque_data.length)];
715 	}
716 }
717 
718 /// The GOAWAY frame. 
719 struct GoAway {
720 	FrameHeader hd;
721 	int last_stream_id;
722 	FrameError error_code;
723 	/// The additional debug data
724 	string opaque_data;
725 	ubyte reserved = 0;
726 
727 	/*
728 	 * Initializes GOAWAY frame with given values. On success, this function takes ownership
729 	 * of |opaque_data|, so caller must not free it. 
730 	 */
731 	this(int _last_stream_id, FrameError _error_code, string _opaque_data) {
732 		hd = FrameHeader(cast(uint)(8 + _opaque_data.length), FrameType.GOAWAY, FrameFlags.NONE, 0);
733 		last_stream_id = _last_stream_id;
734 		error_code = _error_code;
735 		opaque_data = _opaque_data;
736 	}
737 
738 	void free() { if (opaque_data) Mem.free(opaque_data); }
739 
740 
741 	/*
742 	 * Packs GOAWAY frame in wire format and store it in |bufs|.
743 	 * This function expands |bufs| as necessary to store frame.
744 	 *
745 	 * The caller must make sure that bufs.reset() is called
746 	 * before calling this function.
747 	 *
748 	 * This function returns 0 if it succeeds or one of the following
749 	 * negative error codes:
750 	 *
751 	 * ErrorCode.FRAME_SIZE_ERROR
752 	 *     The length of the frame is too large.
753 	 */
754 	ErrorCode pack(Buffers bufs) 
755 	{
756 		ErrorCode rv;
757 		Buffer* buf;
758 		
759 		assert(bufs.head == bufs.cur);
760 		
761 		buf = &bufs.head.buf;
762 		
763 		buf.pos -= FRAME_HDLEN;
764 		
765 		hd.pack((*buf)[]);
766 		
767 		write!uint(buf.last, last_stream_id);
768 		buf.last += 4;
769 		
770 		write!uint(buf.last, error_code);
771 		buf.last += 4;
772 		
773 		rv = bufs.add(cast(string)opaque_data);
774 		
775 		if (rv == ErrorCode.BUFFER_ERROR)
776 			return ErrorCode.FRAME_SIZE_ERROR;
777 
778 		return rv;
779 	}
780 	
781 	/*
782 	 * Unpacks GOAWAY wire format.  The |payload| of length
783 	 * |payloadlen| contains first 8 bytes of payload.  The
784 	 * |var_gift_payload| contains the remaining payload and its 
785 	 * buffer is gifted to the function and then
786 	 * |frame|.  The |var_gift_payload| must be freed by GoAway.free().
787 	 */
788 	void unpack(in ubyte[] payload, ubyte[] var_gift_payload)
789 	{
790 		last_stream_id = read!uint(payload) & STREAM_ID_MASK;
791 		error_code = cast(FrameError) read!uint(payload[4 .. $]);
792 		opaque_data = cast(string)var_gift_payload;
793 	}
794 		
795 	/*
796 	 * Unpacks GOAWAY wire format.  This function only exists
797 	 * for unit test.  After allocating buffer for debug data, this
798 	 * function internally calls http2_frame_unpack_goaway_payload().
799 	 */
800 	void unpack(in ubyte[] payload) 
801 	{
802 		ubyte[] var_gift_payload;
803 		size_t var_gift_payloadlen;
804 		size_t payloadlen = payload.length;
805 		
806 		if (payloadlen > 8) {
807 			var_gift_payloadlen = payloadlen - 8;
808 		} else {
809 			var_gift_payloadlen = 0;
810 		}
811 
812 		if (!var_gift_payloadlen) {
813 			var_gift_payload = null;
814 		} else {
815 			var_gift_payload = Mem.alloc!(ubyte[])(var_gift_payloadlen);						
816 			memcpy(var_gift_payload.ptr, payload.ptr + 8, var_gift_payloadlen);
817 		}
818 		
819 		unpack(payload,	var_gift_payload);
820 	}
821 
822 }
823 
824 /// The WINDOW_UPDATE frame.
825 struct WindowUpdate {    
826 	FrameHeader hd;	
827 	int window_size_increment;	
828 	ubyte reserved = 0;
829 
830 	this(FrameFlags flags, int stream_id,  int _window_size_increment)
831 	{
832 		hd = FrameHeader(4, FrameType.WINDOW_UPDATE, flags, stream_id);
833 		window_size_increment = _window_size_increment;
834 	}
835 	
836 	void free(){}
837 
838 	/*
839 	 * Packs WINDOW_UPDATE frame in wire frame format and store it
840 	 * in |bufs|.
841 	 *
842 	 * The caller must make sure that bufs.reset() is called
843 	 * before calling this function.
844 	 */
845 	void pack(Buffers bufs) {
846 		Buffer* buf;
847 		
848 		assert(bufs.head == bufs.cur);
849 		
850 		buf = &bufs.head.buf;
851 		
852 		assert(buf.available >= 4);
853 		
854 		buf.pos -= FRAME_HDLEN;
855 		
856 		hd.pack((*buf)[]);
857 		
858 		write!uint(buf.last, window_size_increment);
859 		buf.last += 4;
860 	}
861 	
862 	/*
863 	 * Unpacks WINDOW_UPDATE frame byte sequence.
864 	 */
865 	void unpack(in ubyte[] payload) {
866 		window_size_increment = read!uint(payload) & WINDOW_SIZE_INCREMENT_MASK;
867 	}
868 
869 }
870 
871 
872 /*
873  * This union includes all frames to pass them to various function
874  * calls as http2_frame type.  The CONTINUATION frame is omitted
875  * from here because the library deals with it internally.
876  */
877 union Frame
878 {
879 	FrameHeader hd;
880 	Data data;
881 	Headers headers;
882 	Priority priority;
883 	RstStream rst_stream;
884 	Settings settings;
885 	PushPromise push_promise;
886 	Ping ping;
887 	GoAway goaway;
888 	WindowUpdate window_update;
889 
890 	/*
891 	 * Returns the number of padding bytes after payload.  The total
892 	 * padding length is given in the |padlen|.  The returned value does
893 	 * not include the Pad Length field.
894 	 */
895 	size_t trailPadlen(size_t padlen)
896 	{
897 		return padlen - ((hd.flags & FrameFlags.PADDED) > 0);
898 	}
899 
900 	void unpack(in ubyte[] input)
901 	{
902 		const(ubyte)[] payload = input[FRAME_HDLEN .. $];
903 		size_t payloadoff;
904 
905 		hd.unpack(input);
906 
907 		with (FrameType) final switch (hd.type) {
908 			case HEADERS:
909 				payloadoff = cast(size_t) ((hd.flags & FrameFlags.PADDED) > 0);
910 				headers.unpack(payload[payloadoff .. $]);
911 				break;
912 			case PRIORITY:
913 				priority.unpack(payload);
914 				break;
915 			case RST_STREAM:
916 				rst_stream.unpack(payload);
917 				break;
918 			case SETTINGS:
919 				settings.unpack(payload);
920 				break;
921 			case PUSH_PROMISE:
922 				push_promise.unpack(payload);
923 				break;
924 			case PING:
925 				ping.unpack(payload);
926 				break;
927 			case GOAWAY:
928 				goaway.unpack(payload);
929 				break;
930 			case WINDOW_UPDATE:
931 				window_update.unpack(payload);
932 				break;
933 			case DATA:
934 			case CONTINUATION:
935 				break;
936 
937 		}
938 	}
939 
940 	void unpack(Buffers bufs) {
941 		Buffer *buf;
942 		
943 		/* Assuming we have required data in first buffer. We don't decode
944 		   header block so, we don't mind its space */
945 		buf = &bufs.head.buf;
946 		unpack((*buf)[]);
947 	}
948 }
949 
950 /// struct used for HEADERS and PUSH_PROMISE frame
951 struct HeadersAuxData {
952 	DataProvider data_prd;
953 	void *stream_user_data;
954 	
955 	/// error code when request HEADERS is canceled by RST_STREAM while it is in queue. 
956 	FrameError error_code;
957 	
958 	/// nonzero if request HEADERS is canceled.  The error code is stored in |error_code|.
959 	bool canceled;
960 	
961 	/// nonzero if this item should be attached to stream object to make it under priority control
962 	bool attach_stream;
963 }
964 
965 /// struct used for DATA frame
966 struct DataAuxData {
967 	/// The data to be sent for this DATA frame.
968 	DataProvider data_prd;
969 	
970 	/**
971     * The flags of DATA frame.  We use separate flags here and
972     * http2_data frame.  The latter contains flags actually sent to
973     * peer.  This |flags| may contain END_STREAM and only
974     * when |eof| becomes nonzero, flags in http2_data has
975     * END_STREAM set.
976     */
977 	DataFlags flags;
978 
979 	/// The flag to indicate whether EOF was reached or not. Initially |eof| is 0. It becomes 1 after all data were read.
980 	bool eof;
981 
982 	/// The flag to indicate that DataFlags.NO_COPY was used.
983 	bool no_copy; 
984 }
985 
986 enum GoAwayAuxFlags {
987 	NONE = 0x0,
988 	/// indicates that session should be terminated after the transmission of this frame.
989 	TERM_ON_SEND = 0x1,
990 	/// indicates that this GOAWAY is just a notification for graceful shutdown.  
991 	/// No http2_session.goaway_flags should be updated on the reaction to this frame.
992 	SHUTDOWN_NOTICE = 0x2,
993 }
994 
995 /// struct used for GOAWAY frame
996 struct GoAwayAuxData {
997 	GoAwayAuxFlags flags;
998 }
999 
1000 /// Additional data which cannot be stored in Frame struct
1001 union AuxData {
1002 	DataAuxData data;
1003 	HeadersAuxData headers;
1004 	GoAwayAuxData goaway;
1005 }
1006 
1007 class OutboundItem {
1008 	enum NOGC = true;
1009 	import libhttp2.session : Session;
1010 	Frame frame;
1011 	AuxData aux_data;
1012 	long seq;
1013 	
1014 	/// Reset count of weight. See comment for last_cycle
1015 	ulong cycle;
1016 	
1017 	/// The priority used in priority comparion.  Larger is served ealier.
1018 	int weight = OB_EX_WEIGHT;
1019 	
1020 	/// true if this object is queued.
1021 	bool queued;
1022 
1023 	this() { }
1024 
1025 	this(Session session) {
1026 		seq = session.next_seq++;
1027 	}
1028 
1029 	void free() {
1030 
1031 		with (FrameType) switch (frame.hd.type) {
1032 			case HEADERS:
1033 			case CONTINUATION:
1034 				frame.headers.free();
1035 				break;
1036 			case PRIORITY:
1037 				frame.priority.free();
1038 				break;
1039 			case RST_STREAM:
1040 				frame.rst_stream.free();
1041 				break;
1042 			case SETTINGS:
1043 				frame.settings.free();
1044 				break;
1045 			case PUSH_PROMISE:
1046 				frame.push_promise.free();
1047 				break;
1048 			case PING:
1049 				frame.ping.free();
1050 				break;
1051 			case GOAWAY:
1052 				frame.goaway.free();
1053 				break;
1054 			case WINDOW_UPDATE:
1055 				frame.window_update.free();
1056 				break;
1057 			default: break;
1058 		}
1059 	}
1060 
1061 }
1062 
1063 int bytes_compar(const ubyte* a, size_t alen, const ubyte* b, size_t blen) {
1064 	import core.stdc..string : memcmp;
1065 	int rv;
1066 	
1067 	if (alen == blen) {
1068 		return memcmp(a, b, alen);
1069 	}
1070 	
1071 	if (alen < blen) {
1072 		rv = memcmp(a, b, alen);
1073 		
1074 		if (rv == 0) {
1075 			return -1;
1076 		}
1077 		
1078 		return rv;
1079 	}
1080 	
1081 	rv = memcmp(a, b, blen);
1082 	
1083 	if (rv == 0) {
1084 		return 1;
1085 	}
1086 	
1087 	return rv;
1088 }
1089 
1090 // true if everything is fine, false otherwise
1091 bool check(in Setting[] iva) 
1092 {
1093 	foreach (entry; iva) {
1094 		with(Setting) switch (entry.id) {
1095 			case HEADER_TABLE_SIZE:
1096 				if (entry.value > MAX_HEADER_TABLE_SIZE) {
1097 					return false;
1098 				}
1099 				break;
1100 			case MAX_CONCURRENT_STREAMS:
1101 				break;
1102 			case ENABLE_PUSH:
1103 				if (entry.value != 0 && entry.value != 1) {
1104 					return false;
1105 				}
1106 				break;
1107 			case INITIAL_WINDOW_SIZE:
1108 				if (entry.value > cast(uint)MAX_WINDOW_SIZE) {
1109 					return false;
1110 				}
1111 				break;
1112 			case MAX_FRAME_SIZE:
1113 				if (entry.value < MAX_FRAME_SIZE_MIN ||
1114 					entry.value > MAX_FRAME_SIZE_MAX) {
1115 					return false;
1116 				}
1117 				break;
1118 			case MAX_HEADER_LIST_SIZE:
1119 				break;
1120 			default:
1121 				break;
1122 		}
1123 	}
1124 	return true;
1125 }
1126 
1127 void frameSetPad(Buffer* buf, int padlen, bool framehd_only) 
1128 {
1129 	import core.stdc..string : memmove, memset;
1130 	int trail_padlen;
1131 	int newlen;
1132 	
1133 	LOGF("send: padlen=%d, shift left 1 bytes", padlen);
1134 	
1135 	memmove(buf.pos - 1, buf.pos, FRAME_HDLEN);
1136 	
1137 	--buf.pos;
1138 	
1139 	buf.pos[4] |= FrameFlags.PADDED;
1140 	
1141 	newlen = (read!uint(buf.pos) >> 8) + padlen;
1142 	write!uint(buf.pos, cast(uint)((newlen << 8) + buf.pos[3]));
1143 
1144 	if (framehd_only)
1145 		return;
1146 
1147 	trail_padlen = padlen - 1;
1148 	buf.pos[FRAME_HDLEN] = cast(ubyte) trail_padlen;
1149 	
1150 	/* zero out padding */
1151 	memset(buf.last, 0, trail_padlen);
1152 	/* extend buffers trail_padlen bytes, since we ate previous padlen -
1153      trail_padlen byte(s) */
1154 	buf.last += trail_padlen;
1155 }
1156 
1157 /**
1158  * Returns the number of priority field depending on the |flags|.  If
1159  * |flags| has no priority designation, return 0.
1160  */
1161 size_t priorityLength(FrameFlags flags) {
1162 	if (flags & FrameFlags.PRIORITY) {
1163 		return PRIORITY_SPECLEN;
1164 	}
1165 	
1166 	return 0;
1167 }