The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#) https://grpc.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
4.1 KiB

package http2interop
import (
"crypto/tls"
"fmt"
"io"
"log"
)
const (
Preface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
)
func parseFrame(r io.Reader) (Frame, error) {
fh := FrameHeader{}
if err := fh.Parse(r); err != nil {
return nil, err
}
var f Frame
switch fh.Type {
case PingFrameType:
f = &PingFrame{
Header: fh,
}
case SettingsFrameType:
f = &SettingsFrame{
Header: fh,
}
default:
f = &UnknownFrame{
Header: fh,
}
}
if err := f.ParsePayload(r); err != nil {
return nil, err
}
return f, nil
}
func streamFrame(w io.Writer, f Frame) error {
raw, err := f.MarshalBinary()
if err != nil {
return err
}
if _, err := w.Write(raw); err != nil {
return err
}
return nil
}
func getHttp2Conn(addr string) (*tls.Conn, error) {
config := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"h2"},
}
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
return nil, err
}
return conn, nil
}
func testClientShortSettings(addr string, length int) error {
c, err := getHttp2Conn(addr)
if err != nil {
return err
}
defer c.Close()
if _, err := c.Write([]byte(Preface)); err != nil {
return err
}
// Bad, settings, non multiple of 6
sf := &UnknownFrame{
Header: FrameHeader{
Type: SettingsFrameType,
},
Data: make([]byte, length),
}
if err := streamFrame(c, sf); err != nil {
return err
}
for {
frame, err := parseFrame(c)
if err != nil {
return err
}
log.Println(frame)
}
return nil
}
func testClientPrefaceWithStreamId(addr string) error {
c, err := getHttp2Conn(addr)
if err != nil {
return err
}
defer c.Close()
// Good so far
if _, err := c.Write([]byte(Preface)); err != nil {
return err
}
// Bad, settings do not have ids
sf := &SettingsFrame{
Header: FrameHeader{
StreamID: 1,
},
}
if err := streamFrame(c, sf); err != nil {
return err
}
for {
frame, err := parseFrame(c)
if err != nil {
return err
}
log.Println(frame)
}
return nil
}
func testUnknownFrameType(addr string) error {
c, err := getHttp2Conn(addr)
if err != nil {
return err
}
defer c.Close()
if _, err := c.Write([]byte(Preface)); err != nil {
return err
}
// Send some settings, which are part of the client preface
sf := &SettingsFrame{}
if err := streamFrame(c, sf); err != nil {
return err
}
// Write a bunch of invalid frame types.
for ft := ContinuationFrameType + 1; ft != 0; ft++ {
fh := &UnknownFrame{
Header: FrameHeader{
Type: ft,
},
}
if err := streamFrame(c, fh); err != nil {
return err
}
}
pf := &PingFrame{
Data: []byte("01234567"),
}
if err := streamFrame(c, pf); err != nil {
return err
}
for {
frame, err := parseFrame(c)
if err != nil {
return err
}
if npf, ok := frame.(*PingFrame); !ok {
continue
} else {
if string(npf.Data) != string(pf.Data) || npf.Header.Flags&PING_ACK == 0 {
return fmt.Errorf("Bad ping %+v", *npf)
}
return nil
}
}
return nil
}
func testShortPreface(addr string, prefacePrefix string) error {
c, err := getHttp2Conn(addr)
if err != nil {
return err
}
defer c.Close()
if _, err := c.Write([]byte(prefacePrefix)); err != nil {
return err
}
buf := make([]byte, 256)
for ; err == nil; _, err = c.Read(buf) {
}
// TODO: maybe check for a GOAWAY?
return err
}
func testTLSMaxVersion(addr string, version uint16) error {
config := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"h2"},
MaxVersion: version,
}
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
return err
}
defer conn.Close()
buf := make([]byte, 256)
if n, err := conn.Read(buf); err != nil {
if n != 0 {
return fmt.Errorf("Expected no bytes to be read, but was %d", n)
}
return err
}
return nil
}
func testTLSApplicationProtocol(addr string) error {
config := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"h2c"},
}
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
return err
}
defer conn.Close()
buf := make([]byte, 256)
if n, err := conn.Read(buf); err != nil {
if n != 0 {
return fmt.Errorf("Expected no bytes to be read, but was %d", n)
}
return err
}
return nil
}