mirror of
https://github.com/soheilhy/cmux.git
synced 2024-11-10 03:31:52 +08:00
http2: use io.ReadFull
This fixes an issue where an earlier matcher does not sufficiently populate the buffer, preventing HTTP2 from reading enough bytes on the Read call.
This commit is contained in:
parent
99ee7b080d
commit
204cc45a24
47
cmux_test.go
47
cmux_test.go
@ -15,6 +15,8 @@ import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -229,6 +231,51 @@ func TestAny(t *testing.T) {
|
||||
runTestHTTP1Client(t, l.Addr())
|
||||
}
|
||||
|
||||
func TestHTTP2(t *testing.T) {
|
||||
defer leakCheck(t)()
|
||||
errCh := make(chan error)
|
||||
defer func() {
|
||||
select {
|
||||
case err := <-errCh:
|
||||
t.Fatal(err)
|
||||
default:
|
||||
}
|
||||
}()
|
||||
writer, reader := net.Pipe()
|
||||
go func() {
|
||||
if _, err := io.WriteString(writer, http2.ClientPreface); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := writer.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
l := newChanListener()
|
||||
l.connCh <- reader
|
||||
muxl := New(l)
|
||||
// Register a bogus matcher that only reads one byte.
|
||||
muxl.Match(func(r io.Reader) bool {
|
||||
var b [1]byte
|
||||
_, _ = r.Read(b[:])
|
||||
return false
|
||||
})
|
||||
h2l := muxl.Match(HTTP2())
|
||||
go safeServe(errCh, muxl)
|
||||
close(l.connCh)
|
||||
if muxedConn, err := h2l.Accept(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
var b [len(http2.ClientPreface)]byte
|
||||
if _, err := muxedConn.Read(b[:]); err != io.EOF {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(b[:]) != http2.ClientPreface {
|
||||
t.Errorf("got unexpected read %s, expected %s", b, http2.ClientPreface)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPGoRPC(t *testing.T) {
|
||||
defer leakCheck(t)()
|
||||
errCh := make(chan error)
|
||||
|
11
matchers.go
11
matchers.go
@ -2,7 +2,6 @@ package cmux
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@ -77,8 +76,6 @@ func parseRequestLine(line string) (method, uri, proto string, ok bool) {
|
||||
return line[:s1], line[s1+1 : s2], line[s2+1:], true
|
||||
}
|
||||
|
||||
var http2Preface = []byte(http2.ClientPreface)
|
||||
|
||||
// HTTP2 parses the frame header of the first frame to detect whether the
|
||||
// connection is an HTTP2 connection.
|
||||
func HTTP2() Matcher {
|
||||
@ -102,14 +99,12 @@ func HTTP2HeaderField(name, value string) Matcher {
|
||||
}
|
||||
|
||||
func hasHTTP2Preface(r io.Reader) bool {
|
||||
b := make([]byte, len(http2Preface))
|
||||
n, err := r.Read(b)
|
||||
if err != nil {
|
||||
var b [len(http2.ClientPreface)]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
b = b[:n]
|
||||
return bytes.Equal(b, http2Preface)
|
||||
return string(b[:]) == http2.ClientPreface
|
||||
}
|
||||
|
||||
func matchHTTP1Field(r io.Reader, name, value string) (matched bool) {
|
||||
|
Loading…
Reference in New Issue
Block a user