From a098b2c182a6942ccd5469d8ed83392e64badc57 Mon Sep 17 00:00:00 2001
From: iamqizhao <toqizhao@gmail.com>
Date: Mon, 21 Mar 2016 18:23:30 -0700
Subject: [PATCH 1/2] Specialize http2.StreamError when the server reads frames

---
 test/end2end_test.go      | 32 ++++++++++++++++++++++++++++++++
 transport/http2_server.go | 10 ++++++++++
 2 files changed, 42 insertions(+)

diff --git a/test/end2end_test.go b/test/end2end_test.go
index 8b64234b..27179ee3 100644
--- a/test/end2end_test.go
+++ b/test/end2end_test.go
@@ -80,6 +80,9 @@ var (
 		"tkey1": []string{"trailerValue1"},
 		"tkey2": []string{"trailerValue2"},
 	}
+	malformedHTTP2Metadata = metadata.MD{
+		"Key": []string{"foo"},
+	}
 	testAppUA = "myApp1/1.0 myApp2/0.9"
 )
 
@@ -889,6 +892,35 @@ func testMetadataUnaryRPC(t *testing.T, e env) {
 	}
 }
 
+func TestMalformedHTTP2Metadata(t *testing.T) {
+	defer leakCheck(t)()
+	for _, e := range listTestEnv() {
+		testMalformedHTTP2Metadata(t, e)
+	}
+}
+
+func testMalformedHTTP2Metadata(t *testing.T, e env) {
+	te := newTest(t, e)
+	te.startServer()
+	defer te.tearDown()
+	tc := testpb.NewTestServiceClient(te.clientConn())
+
+	payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, 2718)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	req := &testpb.SimpleRequest{
+		ResponseType: testpb.PayloadType_COMPRESSABLE.Enum(),
+		ResponseSize: proto.Int32(314),
+		Payload:      payload,
+	}
+	ctx := metadata.NewContext(context.Background(), malformedHTTP2Metadata)
+	if _, err := tc.UnaryCall(ctx, req); grpc.Code(err) != codes.Internal {
+		t.Fatalf("TestService.UnaryCall(%v, _) = _, %v; want _, %q", ctx, err, codes.Internal)
+	}
+}
+
 func performOneRPC(t *testing.T, tc testpb.TestServiceClient, wg *sync.WaitGroup) {
 	defer wg.Done()
 	const argSize = 2718
diff --git a/transport/http2_server.go b/transport/http2_server.go
index cec441cf..03164236 100644
--- a/transport/http2_server.go
+++ b/transport/http2_server.go
@@ -246,6 +246,16 @@ func (t *http2Server) HandleStreams(handle func(*Stream)) {
 	for {
 		frame, err := t.framer.readFrame()
 		if err != nil {
+			if se, ok := err.(http2.StreamError); ok {
+				t.mu.Lock()
+				s := t.activeStreams[se.StreamID]
+				t.mu.Unlock()
+				if s != nil {
+					t.closeStream(s)
+				}
+				t.controlBuf.put(&resetStream{se.StreamID, se.Code})
+				continue
+			}
 			t.Close()
 			return
 		}

From a31af4bde245ff84f93996fa4c0d9291deefe47d Mon Sep 17 00:00:00 2001
From: iamqizhao <toqizhao@gmail.com>
Date: Tue, 22 Mar 2016 10:56:29 -0700
Subject: [PATCH 2/2] Add some comments to the new test.

---
 test/end2end_test.go | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/test/end2end_test.go b/test/end2end_test.go
index 27179ee3..14f86b1b 100644
--- a/test/end2end_test.go
+++ b/test/end2end_test.go
@@ -80,6 +80,7 @@ var (
 		"tkey1": []string{"trailerValue1"},
 		"tkey2": []string{"trailerValue2"},
 	}
+	// capital "Key" is illegal in HTTP/2.
 	malformedHTTP2Metadata = metadata.MD{
 		"Key": []string{"foo"},
 	}
@@ -892,6 +893,8 @@ func testMetadataUnaryRPC(t *testing.T, e env) {
 	}
 }
 
+// TestMalformedHTTP2Metedata verfies the returned error when the client
+// sends an illegal metadata.
 func TestMalformedHTTP2Metadata(t *testing.T) {
 	defer leakCheck(t)()
 	for _, e := range listTestEnv() {