aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
authorGravatar Craig Tiller <craig.tiller@gmail.com>2015-11-24 17:06:37 -0800
committerGravatar Craig Tiller <craig.tiller@gmail.com>2015-11-24 17:06:37 -0800
commitd6ddc49da3fc1babaa72f0c8e9713b55f9fed2fe (patch)
tree911c7029bb3eb23a61f7ccee6c3c9b6746462ad8 /tools
parent486ea3509e7dc272a6642c5b8e6cb9a68c61c6d7 (diff)
parent945836eade7d8f12f6eb84bc209da13ae7c89b38 (diff)
Merge github.com:grpc/grpc into i-have-no-master
Diffstat (limited to 'tools')
-rw-r--r--tools/doxygen/Doxyfile.core.internal3
-rw-r--r--tools/http2_interop/frameheader.go13
-rw-r--r--tools/http2_interop/http1frame.go49
-rw-r--r--tools/http2_interop/http2interop.go178
-rw-r--r--tools/http2_interop/http2interop_test.go37
-rw-r--r--tools/run_tests/sources_and_headers.json46
-rw-r--r--tools/run_tests/tests.json18
7 files changed, 265 insertions, 79 deletions
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index f4fb52b94b..8dcd8cd42c 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -794,6 +794,7 @@ src/core/channel/noop_filter.h \
src/core/channel/subchannel_call_holder.h \
src/core/client_config/client_config.h \
src/core/client_config/connector.h \
+src/core/client_config/initial_connect_string.h \
src/core/client_config/lb_policies/pick_first.h \
src/core/client_config/lb_policies/round_robin.h \
src/core/client_config/lb_policy.h \
@@ -933,6 +934,8 @@ src/core/channel/noop_filter.c \
src/core/channel/subchannel_call_holder.c \
src/core/client_config/client_config.c \
src/core/client_config/connector.c \
+src/core/client_config/default_initial_connect_string.c \
+src/core/client_config/initial_connect_string.c \
src/core/client_config/lb_policies/pick_first.c \
src/core/client_config/lb_policies/round_robin.c \
src/core/client_config/lb_policy.c \
diff --git a/tools/http2_interop/frameheader.go b/tools/http2_interop/frameheader.go
index 78fe4201f6..84f6fa5c55 100644
--- a/tools/http2_interop/frameheader.go
+++ b/tools/http2_interop/frameheader.go
@@ -58,7 +58,11 @@ func (fh *FrameHeader) MarshalBinary() ([]byte, error) {
buf[0], buf[1], buf[2] = byte(fh.Length>>16), byte(fh.Length>>8), byte(fh.Length)
buf[3] = byte(fh.Type)
buf[4] = fh.Flags
- binary.BigEndian.PutUint32(buf[5:], uint32(fh.StreamID))
+ var res uint32
+ if fh.Reserved {
+ res = 0x80000000
+ }
+ binary.BigEndian.PutUint32(buf[5:], uint32(fh.StreamID)|res)
return buf, nil
}
@@ -89,6 +93,8 @@ func (ft FrameType) String() string {
return "WINDOW_UPDATE"
case ContinuationFrameType:
return "CONTINUATION"
+ case HTTP1FrameType:
+ return "HTTP/1.? (Bad)"
default:
return fmt.Sprintf("UNKNOWN(%d)", byte(ft))
}
@@ -106,4 +112,9 @@ const (
GoAwayFrameType FrameType = 7
WindowUpdateFrameType FrameType = 8
ContinuationFrameType FrameType = 9
+
+ // HTTP1FrameType is not a real type, but rather a convenient way to check if the response
+ // is an http response. The type of a frame header is the 4th byte, which in an http1
+ // response will be "HTTP/1.1 200 OK" or something like that. The character for "P" is 80.
+ HTTP1FrameType FrameType = 80
)
diff --git a/tools/http2_interop/http1frame.go b/tools/http2_interop/http1frame.go
new file mode 100644
index 0000000000..68ab197b65
--- /dev/null
+++ b/tools/http2_interop/http1frame.go
@@ -0,0 +1,49 @@
+package http2interop
+
+import (
+ "bytes"
+ "io"
+ "strings"
+)
+
+// HTTP1Frame is not a real frame, but rather a way to represent an http1.x response.
+type HTTP1Frame struct {
+ Header FrameHeader
+ Data []byte
+}
+
+func (f *HTTP1Frame) GetHeader() *FrameHeader {
+ return &f.Header
+}
+
+func (f *HTTP1Frame) ParsePayload(r io.Reader) error {
+ var buf bytes.Buffer
+ if _, err := io.Copy(&buf, r); err != nil {
+ return err
+ }
+ f.Data = buf.Bytes()
+ return nil
+}
+
+func (f *HTTP1Frame) MarshalPayload() ([]byte, error) {
+ return []byte(string(f.Data)), nil
+}
+
+func (f *HTTP1Frame) MarshalBinary() ([]byte, error) {
+ buf, err := f.Header.MarshalBinary()
+ if err != nil {
+ return nil, err
+ }
+
+ buf = append(buf, f.Data...)
+
+ return buf, nil
+}
+
+func (f *HTTP1Frame) String() string {
+ s := string(f.Data)
+ parts := strings.SplitN(s, "\n", 2)
+ headerleft, _ := f.Header.MarshalBinary()
+
+ return strings.TrimSpace(string(headerleft) + parts[0])
+}
diff --git a/tools/http2_interop/http2interop.go b/tools/http2_interop/http2interop.go
index bef8b0b656..abd7d4cf7d 100644
--- a/tools/http2_interop/http2interop.go
+++ b/tools/http2_interop/http2interop.go
@@ -49,11 +49,16 @@ func parseFrame(r io.Reader) (Frame, error) {
f = &SettingsFrame{
Header: fh,
}
+ case HTTP1FrameType:
+ f = &HTTP1Frame{
+ Header: fh,
+ }
default:
f = &UnknownFrame{
Header: fh,
}
}
+
if err := f.ParsePayload(r); err != nil {
return nil, err
}
@@ -73,13 +78,14 @@ func streamFrame(w io.Writer, f Frame) error {
}
func testClientShortSettings(ctx *HTTP2InteropCtx, length int) error {
- c, err := connect(ctx)
+ conn, err := connect(ctx)
if err != nil {
return err
}
- defer c.Close()
+ defer conn.Close()
+ conn.SetDeadline(time.Now().Add(defaultTimeout))
- if _, err := c.Write([]byte(Preface)); err != nil {
+ if _, err := conn.Write([]byte(Preface)); err != nil {
return err
}
@@ -90,30 +96,28 @@ func testClientShortSettings(ctx *HTTP2InteropCtx, length int) error {
},
Data: make([]byte, length),
}
- if err := streamFrame(c, sf); err != nil {
+ if err := streamFrame(conn, sf); err != nil {
ctx.T.Log("Unable to stream frame", sf)
return err
}
- for {
- if _, err := parseFrame(c); err != nil {
- ctx.T.Log("Unable to parse frame")
- return err
- }
+ if _, err := expectGoAwaySoon(conn); err != nil {
+ return err
}
return nil
}
func testClientPrefaceWithStreamId(ctx *HTTP2InteropCtx) error {
- c, err := connect(ctx)
+ conn, err := connect(ctx)
if err != nil {
return err
}
- defer c.Close()
+ defer conn.Close()
+ conn.SetDeadline(time.Now().Add(defaultTimeout))
// Good so far
- if _, err := c.Write([]byte(Preface)); err != nil {
+ if _, err := conn.Write([]byte(Preface)); err != nil {
return err
}
@@ -123,34 +127,25 @@ func testClientPrefaceWithStreamId(ctx *HTTP2InteropCtx) error {
StreamID: 1,
},
}
- if err := streamFrame(c, sf); err != nil {
+ if err := streamFrame(conn, sf); err != nil {
return err
}
- for {
- if _, err := parseFrame(c); err != nil {
- return err
- }
+ if _, err := expectGoAwaySoon(conn); err != nil {
+ return err
}
-
return nil
}
func testUnknownFrameType(ctx *HTTP2InteropCtx) error {
- c, err := connect(ctx)
+ conn, err := connect(ctx)
if err != nil {
return err
}
- defer c.Close()
-
- if _, err := c.Write([]byte(Preface)); err != nil {
- return err
- }
+ defer conn.Close()
+ conn.SetDeadline(time.Now().Add(defaultTimeout))
- // Send some settings, which are part of the client preface
- sf := &SettingsFrame{}
- if err := streamFrame(c, sf); err != nil {
- ctx.T.Log("Unable to stream frame", sf)
+ if err := http2Connect(conn, nil); err != nil {
return err
}
@@ -161,7 +156,7 @@ func testUnknownFrameType(ctx *HTTP2InteropCtx) error {
Type: ft,
},
}
- if err := streamFrame(c, fh); err != nil {
+ if err := streamFrame(conn, fh); err != nil {
ctx.T.Log("Unable to stream frame", fh)
return err
}
@@ -170,18 +165,19 @@ func testUnknownFrameType(ctx *HTTP2InteropCtx) error {
pf := &PingFrame{
Data: []byte("01234567"),
}
- if err := streamFrame(c, pf); err != nil {
- ctx.T.Log("Unable to stream frame", sf)
+ if err := streamFrame(conn, pf); err != nil {
+ ctx.T.Log("Unable to stream frame", pf)
return err
}
for {
- frame, err := parseFrame(c)
+ frame, err := parseFrame(conn)
if err != nil {
- ctx.T.Log("Unable to parse frame")
+ ctx.T.Log("Unable to parse frame", err)
return err
}
if npf, ok := frame.(*PingFrame); !ok {
+ ctx.T.Log("Got frame", frame.GetHeader().Type)
continue
} else {
if string(npf.Data) != string(pf.Data) || npf.Header.Flags&PING_ACK == 0 {
@@ -195,21 +191,22 @@ func testUnknownFrameType(ctx *HTTP2InteropCtx) error {
}
func testShortPreface(ctx *HTTP2InteropCtx, prefacePrefix string) error {
- c, err := connect(ctx)
+ conn, err := connect(ctx)
if err != nil {
return err
}
- defer c.Close()
+ defer conn.Close()
+ conn.SetDeadline(time.Now().Add(defaultTimeout))
- if _, err := c.Write([]byte(prefacePrefix)); err != nil {
+ if _, err := conn.Write([]byte(prefacePrefix)); err != nil {
return err
}
- buf := make([]byte, 256)
- for ; err == nil; _, err = c.Read(buf) {
+ if _, err := expectGoAwaySoon(conn); err != nil {
+ return err
}
- // TODO: maybe check for a GOAWAY?
- return err
+
+ return nil
}
func testTLSMaxVersion(ctx *HTTP2InteropCtx, version uint16) error {
@@ -222,13 +219,18 @@ func testTLSMaxVersion(ctx *HTTP2InteropCtx, version uint16) error {
defer conn.Close()
conn.SetDeadline(time.Now().Add(defaultTimeout))
- 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)
- }
+ if err := http2Connect(conn, nil); err != nil {
+ return err
+ }
+
+ gf, err := expectGoAway(conn)
+ if err != nil {
return err
}
+ // TODO: make an enum out of this
+ if gf.Code != 0xC {
+ return fmt.Errorf("Expected an Inadequate security code: %v", gf)
+ }
return nil
}
@@ -242,13 +244,18 @@ func testTLSApplicationProtocol(ctx *HTTP2InteropCtx) error {
defer conn.Close()
conn.SetDeadline(time.Now().Add(defaultTimeout))
- 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)
- }
+ if err := http2Connect(conn, nil); err != nil {
+ return err
+ }
+
+ gf, err := expectGoAway(conn)
+ if err != nil {
return err
}
+ // TODO: make an enum out of this
+ if gf.Code != 0xC {
+ return fmt.Errorf("Expected an Inadequate security code: %v", gf)
+ }
return nil
}
@@ -279,16 +286,44 @@ func testTLSBadCipherSuites(ctx *HTTP2InteropCtx) error {
return err
}
+ gf, err := expectGoAway(conn)
+ if err != nil {
+ return err
+ }
+ // TODO: make an enum out of this
+ if gf.Code != 0xC {
+ return fmt.Errorf("Expected an Inadequate security code: %v", gf)
+ }
+ return nil
+}
+
+func expectGoAway(conn net.Conn) (*GoAwayFrame, error) {
+ f, err := parseFrame(conn)
+ if err != nil {
+ return nil, err
+ }
+ if gf, ok := f.(*GoAwayFrame); !ok {
+ return nil, fmt.Errorf("Expected GoAway Frame %+v", f)
+ } else {
+ return gf, nil
+ }
+}
+
+// expectGoAwaySoon checks that a GOAWAY frame eventually comes. Servers usually send
+// the initial settings frames before any data has actually arrived. This function
+// checks that a go away shows.
+func expectGoAwaySoon(conn net.Conn) (*GoAwayFrame, error) {
for {
f, err := parseFrame(conn)
if err != nil {
- return err
+ return nil, err
}
- if gf, ok := f.(*GoAwayFrame); ok {
- return fmt.Errorf("Got goaway frame %d", gf.Code)
+ if gf, ok := f.(*GoAwayFrame); !ok {
+ continue
+ } else {
+ return gf, nil
}
}
- return nil
}
func http2Connect(c net.Conn, sf *SettingsFrame) error {
@@ -304,8 +339,29 @@ func http2Connect(c net.Conn, sf *SettingsFrame) error {
return nil
}
-func connect(ctx *HTTP2InteropCtx) (net.Conn, error) {
- var conn net.Conn
+// CapConn captures connection traffic if Log is non-nil
+type CapConn struct {
+ net.Conn
+ Log func(args ...interface{})
+}
+
+func (c *CapConn) Write(data []byte) (int, error) {
+ if c.Log != nil {
+ c.Log(" SEND: ", data)
+ }
+ return c.Conn.Write(data)
+}
+
+func (c *CapConn) Read(data []byte) (int, error) {
+ n, err := c.Conn.Read(data)
+ if c.Log != nil {
+ c.Log(" RECV: ", data[:n], err)
+ }
+ return n, err
+}
+
+func connect(ctx *HTTP2InteropCtx) (*CapConn, error) {
+ var conn *CapConn
var err error
if !ctx.UseTLS {
conn, err = connectWithoutTls(ctx)
@@ -327,24 +383,22 @@ func buildTlsConfig(ctx *HTTP2InteropCtx) *tls.Config {
NextProtos: []string{"h2"},
ServerName: ctx.authority,
MinVersion: tls.VersionTLS12,
- // TODO(carl-mastrangelo): remove this once all test certificates have been updated.
- InsecureSkipVerify: true,
}
}
-func connectWithoutTls(ctx *HTTP2InteropCtx) (net.Conn, error) {
+func connectWithoutTls(ctx *HTTP2InteropCtx) (*CapConn, error) {
conn, err := net.DialTimeout("tcp", ctx.serverSpec, defaultTimeout)
if err != nil {
return nil, err
}
- return conn, nil
+ return &CapConn{Conn: conn}, nil
}
-func connectWithTls(ctx *HTTP2InteropCtx, config *tls.Config) (*tls.Conn, error) {
+func connectWithTls(ctx *HTTP2InteropCtx, config *tls.Config) (*CapConn, error) {
conn, err := connectWithoutTls(ctx)
if err != nil {
return nil, err
}
- return tls.Client(conn, config), nil
+ return &CapConn{Conn: tls.Client(conn, config)}, nil
}
diff --git a/tools/http2_interop/http2interop_test.go b/tools/http2_interop/http2interop_test.go
index e3d366f2f2..b35d085569 100644
--- a/tools/http2_interop/http2interop_test.go
+++ b/tools/http2_interop/http2interop_test.go
@@ -5,7 +5,6 @@ import (
"crypto/x509"
"flag"
"fmt"
- "io"
"io/ioutil"
"os"
"strconv"
@@ -68,15 +67,25 @@ func (ctx *HTTP2InteropCtx) Close() error {
return nil
}
+func TestClientShortSettings(t *testing.T) {
+ if *testCase != "framing" {
+ t.SkipNow()
+ }
+ ctx := InteropCtx(t)
+ for i := 1; i <= 5; i++ {
+ err := testClientShortSettings(ctx, i)
+ matchError(t, err, "EOF")
+ }
+}
+
func TestShortPreface(t *testing.T) {
if *testCase != "framing" {
t.SkipNow()
}
ctx := InteropCtx(t)
for i := 0; i < len(Preface)-1; i++ {
- if err := testShortPreface(ctx, Preface[:i]+"X"); err != io.EOF {
- t.Error("Expected an EOF but was", err)
- }
+ err := testShortPreface(ctx, Preface[:i]+"X")
+ matchError(t, err, "EOF")
}
}
@@ -90,13 +99,22 @@ func TestUnknownFrameType(t *testing.T) {
}
}
+func TestClientPrefaceWithStreamId(t *testing.T) {
+ if *testCase != "framing" {
+ t.SkipNow()
+ }
+ ctx := InteropCtx(t)
+ err := testClientPrefaceWithStreamId(ctx)
+ matchError(t, err, "EOF")
+}
+
func TestTLSApplicationProtocol(t *testing.T) {
if *testCase != "tls" {
t.SkipNow()
}
ctx := InteropCtx(t)
err := testTLSApplicationProtocol(ctx)
- matchError(t, err, "EOF")
+ matchError(t, err, "EOF", "broken pipe")
}
func TestTLSMaxVersion(t *testing.T) {
@@ -119,15 +137,6 @@ func TestTLSBadCipherSuites(t *testing.T) {
matchError(t, err, "EOF", "Got goaway frame")
}
-func TestClientPrefaceWithStreamId(t *testing.T) {
- if *testCase != "framing" {
- t.SkipNow()
- }
- ctx := InteropCtx(t)
- err := testClientPrefaceWithStreamId(ctx)
- matchError(t, err, "EOF")
-}
-
func matchError(t *testing.T, err error, matches ...string) {
if err == nil {
t.Fatal("Expected an error")
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 9e9257bf5e..4ecffbe3ec 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -871,6 +871,21 @@
"gpr",
"gpr_test_util",
"grpc",
+ "grpc_test_util",
+ "test_tcp_server"
+ ],
+ "headers": [],
+ "language": "c",
+ "name": "set_initial_connect_string_test",
+ "src": [
+ "test/core/client_config/set_initial_connect_string_test.c"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
"grpc_test_util"
],
"headers": [],
@@ -1572,7 +1587,8 @@
"grpc++_test_config",
"grpc++_test_util",
"grpc_test_util",
- "reconnect_server"
+ "reconnect_server",
+ "test_tcp_server"
],
"headers": [
"test/proto/empty.grpc.pb.h",
@@ -14348,6 +14364,7 @@
"src/core/channel/subchannel_call_holder.h",
"src/core/client_config/client_config.h",
"src/core/client_config/connector.h",
+ "src/core/client_config/initial_connect_string.h",
"src/core/client_config/lb_policies/pick_first.h",
"src/core/client_config/lb_policies/round_robin.h",
"src/core/client_config/lb_policy.h",
@@ -14508,6 +14525,9 @@
"src/core/client_config/client_config.h",
"src/core/client_config/connector.c",
"src/core/client_config/connector.h",
+ "src/core/client_config/default_initial_connect_string.c",
+ "src/core/client_config/initial_connect_string.c",
+ "src/core/client_config/initial_connect_string.h",
"src/core/client_config/lb_policies/pick_first.c",
"src/core/client_config/lb_policies/pick_first.h",
"src/core/client_config/lb_policies/round_robin.c",
@@ -14865,6 +14885,7 @@
"src/core/channel/subchannel_call_holder.h",
"src/core/client_config/client_config.h",
"src/core/client_config/connector.h",
+ "src/core/client_config/initial_connect_string.h",
"src/core/client_config/lb_policies/pick_first.h",
"src/core/client_config/lb_policies/round_robin.h",
"src/core/client_config/lb_policy.h",
@@ -15011,6 +15032,9 @@
"src/core/client_config/client_config.h",
"src/core/client_config/connector.c",
"src/core/client_config/connector.h",
+ "src/core/client_config/default_initial_connect_string.c",
+ "src/core/client_config/initial_connect_string.c",
+ "src/core/client_config/initial_connect_string.h",
"src/core/client_config/lb_policies/pick_first.c",
"src/core/client_config/lb_policies/pick_first.h",
"src/core/client_config/lb_policies/round_robin.c",
@@ -15248,7 +15272,8 @@
"gpr",
"gpr_test_util",
"grpc",
- "grpc_test_util"
+ "grpc_test_util",
+ "test_tcp_server"
],
"headers": [
"test/core/util/reconnect_server.h"
@@ -15263,6 +15288,23 @@
{
"deps": [
"gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc_test_util"
+ ],
+ "headers": [
+ "test/core/util/test_tcp_server.h"
+ ],
+ "language": "c",
+ "name": "test_tcp_server",
+ "src": [
+ "test/core/util/test_tcp_server.c",
+ "test/core/util/test_tcp_server.h"
+ ]
+ },
+ {
+ "deps": [
+ "gpr",
"grpc"
],
"headers": [
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index ff0bae7430..179b078263 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -987,6 +987,24 @@
"exclude_configs": [],
"flaky": false,
"language": "c",
+ "name": "set_initial_connect_string_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ]
+ },
+ {
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "exclude_configs": [],
+ "flaky": false,
+ "language": "c",
"name": "sockaddr_utils_test",
"platforms": [
"linux",