http3: send GOAWAY when server is shutting down (#4691)

* send goaway when server is shutting down

* http3: track next stream ID instead of last stream ID for GOAWAYs

* refactor the graceful shutdown integration tests

* http3: improve GOAWAY frame parsing tests

* http3: simplify server graceful shutdown logic

* http3: simplify parsing of GOAWAY frames

* http3: clean up initialization of server contexts

* http3: fix race condition in graceful shutdown logic

---------

Co-authored-by: WeidiDeng <weidi_deng@icloud.com>
This commit is contained in:
Marten Seemann
2024-10-11 23:47:17 -05:00
committed by GitHub
parent 8754d28a6a
commit eaa879f32f
6 changed files with 295 additions and 43 deletions

View File

@@ -66,7 +66,8 @@ func (p *frameParser) ParseNext() (frame, error) {
return parseSettingsFrame(p.r, l)
case 0x3: // CANCEL_PUSH
case 0x5: // PUSH_PROMISE
case 0x7: // GOAWAY
case 0x7:
return parseGoAwayFrame(qr, l)
case 0xd: // MAX_PUSH_ID
case 0x2, 0x6, 0x8, 0x9:
p.conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "")
@@ -194,3 +195,27 @@ func (f *settingsFrame) Append(b []byte) []byte {
}
return b
}
type goAwayFrame struct {
StreamID quic.StreamID
}
func parseGoAwayFrame(r io.ByteReader, l uint64) (*goAwayFrame, error) {
frame := &goAwayFrame{}
cbr := countingByteReader{ByteReader: r}
id, err := quicvarint.Read(&cbr)
if err != nil {
return nil, err
}
if cbr.Read != int(l) {
return nil, errors.New("GOAWAY frame: inconsistent length")
}
frame.StreamID = quic.StreamID(id)
return frame, nil
}
func (f *goAwayFrame) Append(b []byte) []byte {
b = quicvarint.Append(b, 0x7)
b = quicvarint.Append(b, uint64(quicvarint.Len(uint64(f.StreamID))))
return quicvarint.Append(b, uint64(f.StreamID))
}