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}