http2: with Go 1.7 set Request.Context in ServeHTTP handlers

And act the same as HTTP/1.x in Go 1.7.

Updates golang/go#15134

Change-Id: Ib64dd82cc5f8dd60e1680525f664d5b72be11fc6
Reviewed-on: https://go-review.googlesource.com/23220
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
diff --git a/http2/server.go b/http2/server.go
index 3a46db6..a2b6c4b 100644
--- a/http2/server.go
+++ b/http2/server.go
@@ -250,10 +250,14 @@
 //
 // The opts parameter is optional. If nil, default values are used.
 func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+	baseCtx, cancel := serverConnBaseContext(c, opts)
+	defer cancel()
+
 	sc := &serverConn{
 		srv:              s,
 		hs:               opts.baseConfig(),
 		conn:             c,
+		baseCtx:          baseCtx,
 		remoteAddrStr:    c.RemoteAddr().String(),
 		bw:               newBufferedWriter(c),
 		handler:          opts.handler(),
@@ -272,6 +276,7 @@
 		serveG:            newGoroutineLock(),
 		pushEnabled:       true,
 	}
+
 	sc.flow.add(initialWindowSize)
 	sc.inflow.add(initialWindowSize)
 	sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
@@ -373,6 +378,7 @@
 	conn             net.Conn
 	bw               *bufferedWriter // writing to conn
 	handler          http.Handler
+	baseCtx          contextContext
 	framer           *Framer
 	doneServing      chan struct{}         // closed when serverConn.serve ends
 	readFrameCh      chan readFrameResult  // written by serverConn.readFrames
@@ -436,10 +442,12 @@
 // responseWriter's state field.
 type stream struct {
 	// immutable:
-	sc   *serverConn
-	id   uint32
-	body *pipe       // non-nil if expecting DATA frames
-	cw   closeWaiter // closed wait stream transitions to closed state
+	sc        *serverConn
+	id        uint32
+	body      *pipe       // non-nil if expecting DATA frames
+	cw        closeWaiter // closed wait stream transitions to closed state
+	ctx       contextContext
+	cancelCtx func()
 
 	// owned by serverConn's serve loop:
 	bodyBytes        int64   // body bytes seen so far
@@ -1157,6 +1165,7 @@
 	}
 	if st != nil {
 		st.gotReset = true
+		st.cancelCtx()
 		sc.closeStream(st, StreamError{f.StreamID, f.ErrCode})
 	}
 	return nil
@@ -1380,10 +1389,13 @@
 	}
 	sc.maxStreamID = id
 
+	ctx, cancelCtx := contextWithCancel(sc.baseCtx)
 	st = &stream{
-		sc:    sc,
-		id:    id,
-		state: stateOpen,
+		sc:        sc,
+		id:        id,
+		state:     stateOpen,
+		ctx:       ctx,
+		cancelCtx: cancelCtx,
 	}
 	if f.StreamEnded() {
 		st.state = stateHalfClosedRemote
@@ -1617,6 +1629,7 @@
 		Body:       body,
 		Trailer:    trailer,
 	}
+	req = requestWithContext(req, st.ctx)
 	if bodyOpen {
 		// Disabled, per golang.org/issue/14960:
 		// st.reqBuf = sc.getRequestBodyBuf()
@@ -1661,6 +1674,7 @@
 func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
 	didPanic := true
 	defer func() {
+		rw.rws.stream.cancelCtx()
 		if didPanic {
 			e := recover()
 			// Same as net/http: