http2: add support for net/http.Server.ConnState tracking This is required to work with the upcoming rewrite of the httptest.Server's connection tracking in https://go-review.googlesource.com/#/c/15151/ which (at least as of patchset 7) doesn't forcefully tear down a StateNew connection during Server.Wait. That might change. In any case, this adds support for ConnState, which users would expect regardless of protocol in a mixed HTTP/1 and HTTP/2 environment. Change-Id: I124aafec29dda123a018935fa306f465ae99cd97 Reviewed-on: https://go-review.googlesource.com/15913 Reviewed-by: Andrew Gerrand <adg@golang.org>
diff --git a/http2/server.go b/http2/server.go index fde3075..71fb200 100644 --- a/http2/server.go +++ b/http2/server.go
@@ -443,6 +443,15 @@ return stateIdle, nil } +// setConnState calls the net/http ConnState hook for this connection, if configured. +// Note that the net/http package does StateNew and StateClosed for us. +// There is currently no plan for StateHijacked or hijacking HTTP/2 connections. +func (sc *serverConn) setConnState(state http.ConnState) { + if sc.hs.ConnState != nil { + sc.hs.ConnState(sc.conn, state) + } +} + func (sc *serverConn) vlogf(format string, args ...interface{}) { if VerboseLogs { sc.logf(format, args...) @@ -640,6 +649,12 @@ sc.condlogf(err, "error reading preface from client %v: %v", sc.conn.RemoteAddr(), err) return } + // Now that we've got the preface, get us out of the + // "StateNew" state. We can't go directly to idle, though. + // Active means we read some data and anticipate a request. We'll + // do another Active when we get a HEADERS frame. + sc.setConnState(http.StateActive) + sc.setConnState(http.StateIdle) go sc.readFrames() // closed by defer sc.conn.Close above @@ -1087,6 +1102,9 @@ } st.state = stateClosed sc.curOpenStreams-- + if sc.curOpenStreams == 0 { + sc.setConnState(http.StateIdle) + } delete(sc.streams, st.id) if p := st.body; p != nil { p.Close(err) @@ -1263,6 +1281,9 @@ adjustStreamPriority(sc.streams, st.id, f.Priority) } sc.curOpenStreams++ + if sc.curOpenStreams == 1 { + sc.setConnState(http.StateActive) + } sc.req = requestParam{ stream: st, header: make(http.Header),
diff --git a/http2/transport_test.go b/http2/transport_test.go index b7bd629..7b62aa9 100644 --- a/http2/transport_test.go +++ b/http2/transport_test.go
@@ -41,7 +41,7 @@ const body = "sup" st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, body) - }) + }, optOnlyServer) defer st.Close() tr := &Transport{InsecureTLSDial: true}