Remove Go1.6 support (#1492)

diff --git a/.travis.yml b/.travis.yml
index 413881a..22bf250 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,6 @@
 language: go
 
 go:
-  - 1.6.x
   - 1.7.x
   - 1.8.x
   - 1.9.x
diff --git a/README.md b/README.md
index f1f789c..622a5dc 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
 Prerequisites
 -------------
 
-This requires Go 1.6 or later.
+This requires Go 1.7 or later.
 
 Constraints
 -----------
diff --git a/benchmark/benchmark16_test.go b/benchmark/benchmark16_test.go
deleted file mode 100644
index fc33e80..0000000
--- a/benchmark/benchmark16_test.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// +build go1.6,!go1.7
-
-/*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package benchmark
-
-import (
-	"os"
-	"testing"
-
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/benchmark/stats"
-)
-
-func BenchmarkClientStreamc1(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 1, 1, 1, false})
-}
-
-func BenchmarkClientStreamc8(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 8, 1, 1, false})
-}
-
-func BenchmarkClientStreamc64(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 64, 1, 1, false})
-}
-
-func BenchmarkClientStreamc512(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 512, 1, 1, false})
-}
-func BenchmarkClientUnaryc1(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 1, 1, 1, false})
-}
-
-func BenchmarkClientUnaryc8(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 8, 1, 1, false})
-}
-
-func BenchmarkClientUnaryc64(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 64, 1, 1, false})
-}
-
-func BenchmarkClientUnaryc512(b *testing.B) {
-	grpc.EnableTracing = true
-	runStream(b, stats.Features{"", true, 0, 0, 0, 512, 1, 1, false})
-}
-
-func BenchmarkClientStreamNoTracec1(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 1, 1, 1, false})
-}
-
-func BenchmarkClientStreamNoTracec8(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 8, 1, 1, false})
-}
-
-func BenchmarkClientStreamNoTracec64(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 64, 1, 1, false})
-}
-
-func BenchmarkClientStreamNoTracec512(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 512, 1, 1, false})
-}
-func BenchmarkClientUnaryNoTracec1(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 1, 1, 1, false})
-}
-
-func BenchmarkClientUnaryNoTracec8(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 8, 1, 1, false})
-}
-
-func BenchmarkClientUnaryNoTracec64(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 64, 1, 1, false})
-}
-
-func BenchmarkClientUnaryNoTracec512(b *testing.B) {
-	grpc.EnableTracing = false
-	runStream(b, stats.Features{"", false, 0, 0, 0, 512, 1, 1, false})
-	runStream(b, stats.Features{"", false, 0, 0, 0, 512, 1, 1, false})
-}
-
-func TestMain(m *testing.M) {
-	os.Exit(stats.RunTestMain(m))
-}
diff --git a/benchmark/benchmark17_test.go b/benchmark/benchmark_test.go
similarity index 100%
rename from benchmark/benchmark17_test.go
rename to benchmark/benchmark_test.go
diff --git a/clientconn.go b/clientconn.go
index ae64a66..a34bd98 100644
--- a/clientconn.go
+++ b/clientconn.go
@@ -378,7 +378,7 @@
 	if cc.dopts.copts.Dialer == nil {
 		cc.dopts.copts.Dialer = newProxyDialer(
 			func(ctx context.Context, addr string) (net.Conn, error) {
-				return dialContext(ctx, "tcp", addr)
+				return (&net.Dialer{}).DialContext(ctx, "tcp", addr)
 			},
 		)
 	}
diff --git a/examples/README.md b/examples/README.md
index 27a8a85..6d9175c 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -8,7 +8,7 @@
 PREREQUISITES
 -------------
 
-- This requires Go 1.5 or later
+- This requires Go 1.7 or later
 - Requires that [GOPATH is set](https://golang.org/doc/code.html#GOPATH)
 
 ```
diff --git a/go16.go b/go16.go
deleted file mode 100644
index f3dbf21..0000000
--- a/go16.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// +build go1.6,!go1.7
-
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package grpc
-
-import (
-	"fmt"
-	"io"
-	"net"
-	"net/http"
-	"os"
-
-	"golang.org/x/net/context"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/status"
-	"google.golang.org/grpc/transport"
-)
-
-// dialContext connects to the address on the named network.
-func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
-	return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
-}
-
-func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
-	req.Cancel = ctx.Done()
-	if err := req.Write(conn); err != nil {
-		return fmt.Errorf("failed to write the HTTP request: %v", err)
-	}
-	return nil
-}
-
-// toRPCErr converts an error into an error from the status package.
-func toRPCErr(err error) error {
-	if _, ok := status.FromError(err); ok {
-		return err
-	}
-	switch e := err.(type) {
-	case transport.StreamError:
-		return status.Error(e.Code, e.Desc)
-	case transport.ConnectionError:
-		return status.Error(codes.Unavailable, e.Desc)
-	default:
-		switch err {
-		case context.DeadlineExceeded:
-			return status.Error(codes.DeadlineExceeded, err.Error())
-		case context.Canceled:
-			return status.Error(codes.Canceled, err.Error())
-		case ErrClientConnClosing:
-			return status.Error(codes.FailedPrecondition, err.Error())
-		}
-	}
-	return status.Error(codes.Unknown, err.Error())
-}
-
-// convertCode converts a standard Go error into its canonical code. Note that
-// this is only used to translate the error returned by the server applications.
-func convertCode(err error) codes.Code {
-	switch err {
-	case nil:
-		return codes.OK
-	case io.EOF:
-		return codes.OutOfRange
-	case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
-		return codes.FailedPrecondition
-	case os.ErrInvalid:
-		return codes.InvalidArgument
-	case context.Canceled:
-		return codes.Canceled
-	case context.DeadlineExceeded:
-		return codes.DeadlineExceeded
-	}
-	switch {
-	case os.IsExist(err):
-		return codes.AlreadyExists
-	case os.IsNotExist(err):
-		return codes.NotFound
-	case os.IsPermission(err):
-		return codes.PermissionDenied
-	}
-	return codes.Unknown
-}
diff --git a/go17.go b/go17.go
deleted file mode 100644
index de23098..0000000
--- a/go17.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// +build go1.7
-
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package grpc
-
-import (
-	"context"
-	"fmt"
-	"io"
-	"net"
-	"net/http"
-	"os"
-
-	netctx "golang.org/x/net/context"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/status"
-	"google.golang.org/grpc/transport"
-)
-
-// dialContext connects to the address on the named network.
-func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
-	return (&net.Dialer{}).DialContext(ctx, network, address)
-}
-
-func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
-	req = req.WithContext(ctx)
-	if err := req.Write(conn); err != nil {
-		return fmt.Errorf("failed to write the HTTP request: %v", err)
-	}
-	return nil
-}
-
-// toRPCErr converts an error into an error from the status package.
-func toRPCErr(err error) error {
-	if _, ok := status.FromError(err); ok {
-		return err
-	}
-	switch e := err.(type) {
-	case transport.StreamError:
-		return status.Error(e.Code, e.Desc)
-	case transport.ConnectionError:
-		return status.Error(codes.Unavailable, e.Desc)
-	default:
-		switch err {
-		case context.DeadlineExceeded, netctx.DeadlineExceeded:
-			return status.Error(codes.DeadlineExceeded, err.Error())
-		case context.Canceled, netctx.Canceled:
-			return status.Error(codes.Canceled, err.Error())
-		case ErrClientConnClosing:
-			return status.Error(codes.FailedPrecondition, err.Error())
-		}
-	}
-	return status.Error(codes.Unknown, err.Error())
-}
-
-// convertCode converts a standard Go error into its canonical code. Note that
-// this is only used to translate the error returned by the server applications.
-func convertCode(err error) codes.Code {
-	switch err {
-	case nil:
-		return codes.OK
-	case io.EOF:
-		return codes.OutOfRange
-	case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
-		return codes.FailedPrecondition
-	case os.ErrInvalid:
-		return codes.InvalidArgument
-	case context.Canceled, netctx.Canceled:
-		return codes.Canceled
-	case context.DeadlineExceeded, netctx.DeadlineExceeded:
-		return codes.DeadlineExceeded
-	}
-	switch {
-	case os.IsExist(err):
-		return codes.AlreadyExists
-	case os.IsNotExist(err):
-		return codes.NotFound
-	case os.IsPermission(err):
-		return codes.PermissionDenied
-	}
-	return codes.Unknown
-}
diff --git a/naming/go17.go b/naming/go17.go
index a537b08..8bdf21e 100644
--- a/naming/go17.go
+++ b/naming/go17.go
@@ -1,4 +1,4 @@
-// +build go1.6, !go1.8
+// +build go1.7, !go1.8
 
 /*
  *
diff --git a/naming/go17_test.go b/naming/go17_test.go
index db39b9a..d1de221 100644
--- a/naming/go17_test.go
+++ b/naming/go17_test.go
@@ -1,4 +1,4 @@
-// +build go1.6, !go1.8
+// +build go1.7, !go1.8
 
 /*
  *
diff --git a/proxy.go b/proxy.go
index 2d40236..3e17efe 100644
--- a/proxy.go
+++ b/proxy.go
@@ -82,7 +82,8 @@
 		Header: map[string][]string{"User-Agent": {grpcUA}},
 	})
 
-	if err := sendHTTPRequest(ctx, req, conn); err != nil {
+	req = req.WithContext(ctx)
+	if err := req.Write(conn); err != nil {
 		return nil, fmt.Errorf("failed to write the HTTP request: %v", err)
 	}
 
diff --git a/rpc_util.go b/rpc_util.go
index aa0c6b6..b80ca66 100644
--- a/rpc_util.go
+++ b/rpc_util.go
@@ -21,10 +21,12 @@
 import (
 	"bytes"
 	"compress/gzip"
+	stdctx "context"
 	"encoding/binary"
 	"io"
 	"io/ioutil"
 	"math"
+	"os"
 	"sync"
 	"time"
 
@@ -410,6 +412,57 @@
 	return
 }
 
+// toRPCErr converts an error into an error from the status package.
+func toRPCErr(err error) error {
+	if _, ok := status.FromError(err); ok {
+		return err
+	}
+	switch e := err.(type) {
+	case transport.StreamError:
+		return status.Error(e.Code, e.Desc)
+	case transport.ConnectionError:
+		return status.Error(codes.Unavailable, e.Desc)
+	default:
+		switch err {
+		case context.DeadlineExceeded, stdctx.DeadlineExceeded:
+			return status.Error(codes.DeadlineExceeded, err.Error())
+		case context.Canceled, stdctx.Canceled:
+			return status.Error(codes.Canceled, err.Error())
+		case ErrClientConnClosing:
+			return status.Error(codes.FailedPrecondition, err.Error())
+		}
+	}
+	return status.Error(codes.Unknown, err.Error())
+}
+
+// convertCode converts a standard Go error into its canonical code. Note that
+// this is only used to translate the error returned by the server applications.
+func convertCode(err error) codes.Code {
+	switch err {
+	case nil:
+		return codes.OK
+	case io.EOF:
+		return codes.OutOfRange
+	case io.ErrClosedPipe, io.ErrNoProgress, io.ErrShortBuffer, io.ErrShortWrite, io.ErrUnexpectedEOF:
+		return codes.FailedPrecondition
+	case os.ErrInvalid:
+		return codes.InvalidArgument
+	case context.Canceled, stdctx.Canceled:
+		return codes.Canceled
+	case context.DeadlineExceeded, stdctx.DeadlineExceeded:
+		return codes.DeadlineExceeded
+	}
+	switch {
+	case os.IsExist(err):
+		return codes.AlreadyExists
+	case os.IsNotExist(err):
+		return codes.NotFound
+	case os.IsPermission(err):
+		return codes.PermissionDenied
+	}
+	return codes.Unknown
+}
+
 // Code returns the error code for err if it was produced by the rpc system.
 // Otherwise, it returns codes.Unknown.
 //
diff --git a/test/end2end_test.go b/test/end2end_test.go
index 0add563..ab15120 100644
--- a/test/end2end_test.go
+++ b/test/end2end_test.go
@@ -2874,7 +2874,7 @@
 	defer leakcheck.Check(t)
 	for _, e := range listTestEnv() {
 		if e.name == "handler-tls" {
-			// In race mode, with go1.6, the test never returns with handler_server.
+			// Fails with RST_STREAM / FLOW_CONTROL_ERROR
 			continue
 		}
 		testRetry(t, e)
diff --git a/transport/go16.go b/transport/go16.go
deleted file mode 100644
index 7cffee1..0000000
--- a/transport/go16.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +build go1.6,!go1.7
-
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package transport
-
-import (
-	"net"
-
-	"google.golang.org/grpc/codes"
-
-	"golang.org/x/net/context"
-)
-
-// dialContext connects to the address on the named network.
-func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
-	return (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
-}
-
-// ContextErr converts the error from context package into a StreamError.
-func ContextErr(err error) StreamError {
-	switch err {
-	case context.DeadlineExceeded:
-		return streamErrorf(codes.DeadlineExceeded, "%v", err)
-	case context.Canceled:
-		return streamErrorf(codes.Canceled, "%v", err)
-	}
-	return streamErrorf(codes.Internal, "Unexpected error from context packet: %v", err)
-}
diff --git a/transport/go17.go b/transport/go17.go
deleted file mode 100644
index 2464e69..0000000
--- a/transport/go17.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// +build go1.7
-
-/*
- *
- * Copyright 2016 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package transport
-
-import (
-	"context"
-	"net"
-
-	"google.golang.org/grpc/codes"
-
-	netctx "golang.org/x/net/context"
-)
-
-// dialContext connects to the address on the named network.
-func dialContext(ctx context.Context, network, address string) (net.Conn, error) {
-	return (&net.Dialer{}).DialContext(ctx, network, address)
-}
-
-// ContextErr converts the error from context package into a StreamError.
-func ContextErr(err error) StreamError {
-	switch err {
-	case context.DeadlineExceeded, netctx.DeadlineExceeded:
-		return streamErrorf(codes.DeadlineExceeded, "%v", err)
-	case context.Canceled, netctx.Canceled:
-		return streamErrorf(codes.Canceled, "%v", err)
-	}
-	return streamErrorf(codes.Internal, "Unexpected error from context packet: %v", err)
-}
diff --git a/transport/http2_client.go b/transport/http2_client.go
index 0b4846f..1abb62e 100644
--- a/transport/http2_client.go
+++ b/transport/http2_client.go
@@ -109,7 +109,7 @@
 	if fn != nil {
 		return fn(ctx, addr)
 	}
-	return dialContext(ctx, "tcp", addr)
+	return (&net.Dialer{}).DialContext(ctx, "tcp", addr)
 }
 
 func isTemporary(err error) bool {
@@ -148,11 +148,9 @@
 	ctx, cancel := context.WithCancel(ctx)
 	connectCtx, connectCancel := context.WithTimeout(ctx, timeout)
 	defer func() {
+		connectCancel()
 		if err != nil {
 			cancel()
-			// Don't call connectCancel in success path due to a race in Go 1.6:
-			// https://github.com/golang/go/issues/15078.
-			connectCancel()
 		}
 	}()
 
diff --git a/transport/transport.go b/transport/transport.go
index e4a3540..bde8fa5 100644
--- a/transport/transport.go
+++ b/transport/transport.go
@@ -21,6 +21,7 @@
 package transport // import "google.golang.org/grpc/transport"
 
 import (
+	stdctx "context"
 	"fmt"
 	"io"
 	"net"
@@ -718,6 +719,17 @@
 	}
 }
 
+// ContextErr converts the error from context package into a StreamError.
+func ContextErr(err error) StreamError {
+	switch err {
+	case context.DeadlineExceeded, stdctx.DeadlineExceeded:
+		return streamErrorf(codes.DeadlineExceeded, "%v", err)
+	case context.Canceled, stdctx.Canceled:
+		return streamErrorf(codes.Canceled, "%v", err)
+	}
+	return streamErrorf(codes.Internal, "Unexpected error from context packet: %v", err)
+}
+
 // GoAwayReason contains the reason for the GoAway frame received.
 type GoAwayReason uint8
 
diff --git a/vet.sh b/vet.sh
index a3e8ef9..9ef4837 100755
--- a/vet.sh
+++ b/vet.sh
@@ -63,7 +63,6 @@
 git ls-files "*.go" | xargs sed -i 's:"golang.org/x/net/context":"context":'
 set +o pipefail
 # TODO: Stop filtering pb.go files once golang/protobuf#214 is fixed.
-# TODO: Remove clientconn exception once go1.6 support is removed.
 go tool vet -all . 2>&1 | grep -vF '.pb.go:' | tee /dev/stderr | (! read)
 set -o pipefail
 git reset --hard HEAD