2
0
mirror of https://github.com/soheilhy/cmux.git synced 2024-09-20 02:55:46 +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:
Tamir Duberstein 2016-02-21 05:05:05 -05:00
parent 99ee7b080d
commit 204cc45a24
2 changed files with 50 additions and 8 deletions

View File

@ -15,6 +15,8 @@ import (
"sync/atomic" "sync/atomic"
"testing" "testing"
"time" "time"
"golang.org/x/net/http2"
) )
const ( const (
@ -229,6 +231,51 @@ func TestAny(t *testing.T) {
runTestHTTP1Client(t, l.Addr()) 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) { func TestHTTPGoRPC(t *testing.T) {
defer leakCheck(t)() defer leakCheck(t)()
errCh := make(chan error) errCh := make(chan error)

View File

@ -2,7 +2,6 @@ package cmux
import ( import (
"bufio" "bufio"
"bytes"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "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 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 // HTTP2 parses the frame header of the first frame to detect whether the
// connection is an HTTP2 connection. // connection is an HTTP2 connection.
func HTTP2() Matcher { func HTTP2() Matcher {
@ -102,14 +99,12 @@ func HTTP2HeaderField(name, value string) Matcher {
} }
func hasHTTP2Preface(r io.Reader) bool { func hasHTTP2Preface(r io.Reader) bool {
b := make([]byte, len(http2Preface)) var b [len(http2.ClientPreface)]byte
n, err := r.Read(b) if _, err := io.ReadFull(r, b[:]); err != nil {
if err != nil {
return false return false
} }
b = b[:n] return string(b[:]) == http2.ClientPreface
return bytes.Equal(b, http2Preface)
} }
func matchHTTP1Field(r io.Reader, name, value string) (matched bool) { func matchHTTP1Field(r io.Reader, name, value string) (matched bool) {