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