| // Copyright 2019 The gRPC Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package http2interop |
| |
| import ( |
| "fmt" |
| "time" |
| ) |
| |
| // Section 6.5 says the minimum SETTINGS_MAX_FRAME_SIZE is 16,384 |
| func testSmallMaxFrameSize(ctx *HTTP2InteropCtx) error { |
| conn, err := connect(ctx) |
| if err != nil { |
| return err |
| } |
| defer conn.Close() |
| conn.SetDeadline(time.Now().Add(defaultTimeout)) |
| |
| sf := &SettingsFrame{ |
| Params: []SettingsParameter{{ |
| Identifier: SettingsMaxFrameSize, |
| Value: 1<<14 - 1, // 1 less than the smallest maximum |
| }}, |
| } |
| |
| if err := http2Connect(conn, sf); err != nil { |
| return err |
| } |
| |
| if _, err := expectGoAwaySoon(conn); err != nil { |
| return err |
| } |
| |
| return nil |
| } |
| |
| // Section 6.5.3 says all settings frames must be acked. |
| func testAllSettingsFramesAcked(ctx *HTTP2InteropCtx) error { |
| conn, err := connect(ctx) |
| if err != nil { |
| return err |
| } |
| defer conn.Close() |
| conn.SetDeadline(time.Now().Add(defaultTimeout)) |
| |
| sf := &SettingsFrame{} |
| if err := http2Connect(conn, sf); err != nil { |
| return err |
| } |
| |
| // The spec says "The values in the SETTINGS frame MUST be processed in the order they |
| // appear. [...] Once all values have been processed, the recipient MUST immediately |
| // emit a SETTINGS frame with the ACK flag set." From my understanding, processing all |
| // of no values warrants an ack per frame. |
| for i := 0; i < 10; i++ { |
| if err := streamFrame(conn, sf); err != nil { |
| return err |
| } |
| } |
| |
| var settingsFramesReceived = 0 |
| // The server by default sends a settings frame as part of the handshake, and another |
| // after the receipt of the initial settings frame as part of our connection preface. |
| // This means we expected 1 + 1 + 10 = 12 settings frames in return, with all but the |
| // first having the ack bit. |
| for settingsFramesReceived < 12 { |
| f, err := parseFrame(conn) |
| if err != nil { |
| return err |
| } |
| |
| // Other frames come down the wire too, including window update. Just ignore those. |
| if f, ok := f.(*SettingsFrame); ok { |
| settingsFramesReceived += 1 |
| if settingsFramesReceived == 1 { |
| if f.Header.Flags&SETTINGS_FLAG_ACK > 0 { |
| return fmt.Errorf("settings frame should not have used ack: %v", f) |
| } |
| continue |
| } |
| |
| if f.Header.Flags&SETTINGS_FLAG_ACK == 0 { |
| return fmt.Errorf("settings frame should have used ack: %v", f) |
| } |
| if len(f.Params) != 0 { |
| return fmt.Errorf("settings ack cannot have params: %v", f) |
| } |
| } |
| } |
| |
| return nil |
| } |