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