1package http2interop
2
3import (
4	"fmt"
5	"time"
6)
7
8// Section 6.5 says the minimum SETTINGS_MAX_FRAME_SIZE is 16,384
9func testSmallMaxFrameSize(ctx *HTTP2InteropCtx) error {
10	conn, err := connect(ctx)
11	if err != nil {
12		return err
13	}
14	defer conn.Close()
15	conn.SetDeadline(time.Now().Add(defaultTimeout))
16
17	sf := &SettingsFrame{
18		Params: []SettingsParameter{{
19			Identifier: SettingsMaxFrameSize,
20			Value:      1<<14 - 1, // 1 less than the smallest maximum
21		}},
22	}
23
24	if err := http2Connect(conn, sf); err != nil {
25		return err
26	}
27
28	if _, err := expectGoAwaySoon(conn); err != nil {
29		return err
30	}
31
32	return nil
33}
34
35// Section 6.5.3 says all settings frames must be acked.
36func testAllSettingsFramesAcked(ctx *HTTP2InteropCtx) error {
37	conn, err := connect(ctx)
38	if err != nil {
39		return err
40	}
41	defer conn.Close()
42	conn.SetDeadline(time.Now().Add(defaultTimeout))
43
44	sf := &SettingsFrame{}
45	if err := http2Connect(conn, sf); err != nil {
46		return err
47	}
48
49	// The spec says "The values in the SETTINGS frame MUST be processed in the order they
50	// appear. [...] Once all values have been processed, the recipient MUST immediately
51	// emit a SETTINGS frame with the ACK flag set."  From my understanding, processing all
52	// of no values warrants an ack per frame.
53	for i := 0; i < 10; i++ {
54		if err := streamFrame(conn, sf); err != nil {
55			return err
56		}
57	}
58
59	var settingsFramesReceived = 0
60	// The server by default sends a settings frame as part of the handshake, and another
61	// after the receipt of the initial settings frame as part of our conneection preface.
62	// This means we expected 1 + 1 + 10 = 12 settings frames in return, with all but the
63	// first having the ack bit.
64	for settingsFramesReceived < 12 {
65		f, err := parseFrame(conn)
66		if err != nil {
67			return err
68		}
69
70		// Other frames come down the wire too, including window update.  Just ignore those.
71		if f, ok := f.(*SettingsFrame); ok {
72			settingsFramesReceived += 1
73			if settingsFramesReceived == 1 {
74				if f.Header.Flags&SETTINGS_FLAG_ACK > 0 {
75					return fmt.Errorf("settings frame should not have used ack: %v")
76				}
77				continue
78			}
79
80			if f.Header.Flags&SETTINGS_FLAG_ACK == 0 {
81				return fmt.Errorf("settings frame should have used ack: %v", f)
82			}
83			if len(f.Params) != 0 {
84				return fmt.Errorf("settings ack cannot have params: %v", f)
85			}
86		}
87	}
88
89	return nil
90}
91