2
0
mirror of https://github.com/soheilhy/cmux.git synced 2024-09-20 02:55:46 +08:00

fix: cause http2.serverConn.unackedSettings ack_mystery

This commit is contained in:
luke 2022-09-29 02:39:48 +08:00
parent 88b0be7739
commit 677b4b20e7
2 changed files with 32 additions and 1 deletions

View File

@ -29,6 +29,7 @@ type bufferedReader struct {
buffer bytes.Buffer buffer bytes.Buffer
bufferRead int bufferRead int
bufferSize int bufferSize int
stagePoint int
sniffing bool sniffing bool
lastErr error lastErr error
} }
@ -65,3 +66,11 @@ func (s *bufferedReader) reset(snif bool) {
s.bufferRead = 0 s.bufferRead = 0
s.bufferSize = s.buffer.Len() s.bufferSize = s.buffer.Len()
} }
func (s *bufferedReader) newStage() {
s.stagePoint = s.buffer.Len()
}
func (s *bufferedReader) discard() {
s.buffer.Truncate(s.stagePoint)
}

View File

@ -217,11 +217,28 @@ func matchHTTP1Field(r io.Reader, name string, matches func(string) bool) (match
return matches(req.Header.Get(name)) return matches(req.Header.Get(name))
} }
type stageReader interface {
io.Reader
newStage()
discard()
}
type nonStageReader struct{ io.Reader }
func (nonStageReader) newStage() {}
func (nonStageReader) discard() {}
func matchHTTP2Field(w io.Writer, r io.Reader, name string, matches func(string) bool) (matched bool) { func matchHTTP2Field(w io.Writer, r io.Reader, name string, matches func(string) bool) (matched bool) {
if !hasHTTP2Preface(r) { if !hasHTTP2Preface(r) {
return false return false
} }
sr := (stageReader)(nil)
if sr, _ = r.(stageReader); sr == nil {
sr = nonStageReader{}
}
waitAcks := 0
done := false done := false
framer := http2.NewFramer(w, r) framer := http2.NewFramer(w, r)
hdec := hpack.NewDecoder(uint32(4<<10), func(hf hpack.HeaderField) { hdec := hpack.NewDecoder(uint32(4<<10), func(hf hpack.HeaderField) {
@ -233,6 +250,7 @@ func matchHTTP2Field(w io.Writer, r io.Reader, name string, matches func(string)
} }
}) })
for { for {
sr.newStage()
f, err := framer.ReadFrame() f, err := framer.ReadFrame()
if err != nil { if err != nil {
return false return false
@ -243,11 +261,15 @@ func matchHTTP2Field(w io.Writer, r io.Reader, name string, matches func(string)
// Sender acknoweldged the SETTINGS frame. No need to write // Sender acknoweldged the SETTINGS frame. No need to write
// SETTINGS again. // SETTINGS again.
if f.IsAck() { if f.IsAck() {
// Avoid causing golang.org/x/net/http2.serverConn.unackedSettings PROTOCOL_ERROR
sr.discard()
waitAcks--
break break
} }
if err := framer.WriteSettings(); err != nil { if err := framer.WriteSettings(); err != nil {
return false return false
} }
waitAcks++
case *http2.ContinuationFrame: case *http2.ContinuationFrame:
if _, err := hdec.Write(f.HeaderBlockFragment()); err != nil { if _, err := hdec.Write(f.HeaderBlockFragment()); err != nil {
return false return false
@ -260,7 +282,7 @@ func matchHTTP2Field(w io.Writer, r io.Reader, name string, matches func(string)
done = done || f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0 done = done || f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0
} }
if done { if done && waitAcks == 0 {
return matched return matched
} }
} }